Blender V4.3
sequencer_channels_draw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "DNA_scene_types.h"
12#include "DNA_screen_types.h"
13
14#include "BKE_context.hh"
15#include "BKE_screen.hh"
16
17#include "BLI_blenlib.h"
18#include "BLI_utildefines.h"
19
20#include "ED_screen.hh"
21
22#include "GPU_matrix.hh"
23#include "GPU_vertex_buffer.hh"
24
25#include "RNA_prototypes.hh"
26
27#include "SEQ_channels.hh"
28#include "SEQ_sequencer.hh"
29#include "SEQ_time.hh"
30
31#include "UI_interface.hh"
32#include "UI_resources.hh"
33#include "UI_view2d.hh"
34
35#include "WM_api.hh"
36
37/* Own include. */
38#include "sequencer_intern.hh"
39
40static float draw_offset_get(const View2D *timeline_region_v2d)
41{
42 return timeline_region_v2d->cur.ymin;
43}
44
45static float channel_height_pixelspace_get(const View2D *timeline_region_v2d)
46{
47 return UI_view2d_view_to_region_y(timeline_region_v2d, 1.0f) -
48 UI_view2d_view_to_region_y(timeline_region_v2d, 0.0f);
49}
50
51static float frame_width_pixelspace_get(const View2D *timeline_region_v2d)
52{
53
54 return UI_view2d_view_to_region_x(timeline_region_v2d, 1.0f) -
55 UI_view2d_view_to_region_x(timeline_region_v2d, 0.0f);
56}
57
58static float icon_width_get(const SeqChannelDrawContext *context)
59{
60 return (U.widget_unit * 0.8 * context->scale);
61}
62
63static float widget_y_offset(const SeqChannelDrawContext *context)
64{
65 return ((context->channel_height / context->scale) - icon_width_get(context)) / 2;
66}
67
68static float channel_index_y_min(const SeqChannelDrawContext *context, const int index)
69{
70 float y = (index - context->draw_offset) * context->channel_height;
71 y /= context->scale;
72 return y;
73}
74
76 int r_channel_range[2])
77{
78 /* Channel 0 is not usable, so should never be drawn. */
79 r_channel_range[0] = max_ii(1, floor(context->timeline_region_v2d->cur.ymin));
80 r_channel_range[1] = ceil(context->timeline_region_v2d->cur.ymax);
81
82 rctf strip_boundbox;
83 BLI_rctf_init(&strip_boundbox, 0.0f, 0.0f, 1.0f, r_channel_range[1]);
84 SEQ_timeline_expand_boundbox(context->scene, context->seqbase, &strip_boundbox);
85 CLAMP(r_channel_range[0], strip_boundbox.ymin, strip_boundbox.ymax);
86 CLAMP(r_channel_range[1], strip_boundbox.ymin, SEQ_MAX_CHANNELS);
87}
88
89static std::string draw_channel_widget_tooltip(bContext * /*C*/, void *argN, const char * /*tip*/)
90{
91 char *dyn_tooltip = static_cast<char *>(argN);
92 return dyn_tooltip;
93}
94
96 uiBlock *block,
97 const int channel_index,
98 const float offset)
99{
100 float y = channel_index_y_min(context, channel_index) + widget_y_offset(context);
101
102 const float width = icon_width_get(context);
103 SeqTimelineChannel *channel = SEQ_channel_get_by_index(context->channels, channel_index);
104 const int icon = SEQ_channel_is_muted(channel) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT;
105
106 PointerRNA ptr = RNA_pointer_create(&context->scene->id, &RNA_SequenceTimelineChannel, channel);
107 PropertyRNA *hide_prop = RNA_struct_type_find_property(&RNA_SequenceTimelineChannel, "mute");
108
110 uiBut *but = uiDefIconButR_prop(block,
112 1,
113 icon,
114 context->v2d->cur.xmax / context->scale - offset,
115 y,
116 width,
117 width,
118 &ptr,
119 hide_prop,
120 0,
121 0,
122 0,
123 nullptr);
124
125 char *tooltip = BLI_sprintfN(
126 "%s channel %d", SEQ_channel_is_muted(channel) ? "Unmute" : "Mute", channel_index);
128
129 return width;
130}
131
133 uiBlock *block,
134 const int channel_index,
135 const float offset)
136{
137
138 float y = channel_index_y_min(context, channel_index) + widget_y_offset(context);
139 const float width = icon_width_get(context);
140
141 SeqTimelineChannel *channel = SEQ_channel_get_by_index(context->channels, channel_index);
142 const int icon = SEQ_channel_is_locked(channel) ? ICON_LOCKED : ICON_UNLOCKED;
143
144 PointerRNA ptr = RNA_pointer_create(&context->scene->id, &RNA_SequenceTimelineChannel, channel);
145 PropertyRNA *hide_prop = RNA_struct_type_find_property(&RNA_SequenceTimelineChannel, "lock");
146
148 uiBut *but = uiDefIconButR_prop(block,
150 1,
151 icon,
152 context->v2d->cur.xmax / context->scale - offset,
153 y,
154 width,
155 width,
156 &ptr,
157 hide_prop,
158 0,
159 0,
160 0,
161 "");
162
163 char *tooltip = BLI_sprintfN(
164 "%s channel %d", SEQ_channel_is_locked(channel) ? "Unlock" : "Lock", channel_index);
166
167 return width;
168}
169
170static bool channel_is_being_renamed(const SpaceSeq *sseq, const int channel_index)
171{
172 return sseq->runtime->rename_channel_index == channel_index;
173}
174
175static float text_size_get(const SeqChannelDrawContext *context)
176{
177 const uiStyle *style = UI_style_get_dpi();
178 return UI_fontstyle_height_max(&style->widget) * 1.5f * context->scale;
179}
180
181/* TODO: decide what gets priority - label or buttons. */
183 const int channel_index,
184 const float used_width)
185{
186 float text_size = text_size_get(context);
187 float margin = (context->channel_height / context->scale - text_size) / 2.0f;
188 float y = channel_index_y_min(context, channel_index) + margin;
189
190 float margin_x = icon_width_get(context) * 0.65;
191 float width = max_ff(0.0f, context->v2d->cur.xmax / context->scale - used_width);
192
193 /* Text input has its own margin. Prevent text jumping around and use as much space as possible.
194 */
195 if (channel_is_being_renamed(CTX_wm_space_seq(context->C), channel_index)) {
196 float input_box_margin = icon_width_get(context) * 0.5f;
197 margin_x -= input_box_margin;
198 width += input_box_margin;
199 }
200
201 rctf rect;
202 BLI_rctf_init(&rect, margin_x, margin_x + width, y, y + text_size);
203 return rect;
204}
205
207 uiBlock *block,
208 const int channel_index,
209 const float used_width)
210{
211 SpaceSeq *sseq = CTX_wm_space_seq(context->C);
212 rctf rect = label_rect_init(context, channel_index, used_width);
213
214 if (BLI_rctf_size_y(&rect) <= 1.0f || BLI_rctf_size_x(&rect) <= 1.0f) {
215 return;
216 }
217
218 if (channel_is_being_renamed(sseq, channel_index)) {
219 SeqTimelineChannel *channel = SEQ_channel_get_by_index(context->channels, channel_index);
221 &context->scene->id, &RNA_SequenceTimelineChannel, channel);
223
225 uiBut *but = uiDefButR(block,
227 1,
228 "",
229 rect.xmin,
230 rect.ymin,
231 BLI_rctf_size_x(&rect),
232 BLI_rctf_size_y(&rect),
233 &ptr,
235 -1,
236 0,
237 0,
238 nullptr);
240
241 if (UI_but_active_only(context->C, context->region, block, but) == false) {
242 sseq->runtime->rename_channel_index = 0;
243 }
244
245 WM_event_add_notifier(context->C, NC_SCENE | ND_SEQUENCER, context->scene);
246 }
247 else {
248 const char *label = SEQ_channel_name_get(context->channels, channel_index);
249 uiDefBut(block,
251 0,
252 label,
253 rect.xmin,
254 rect.ymin,
255 rect.xmax - rect.xmin,
256 (rect.ymax - rect.ymin),
257 nullptr,
258 0,
259 0,
260 nullptr);
261 }
262}
263
265{
267 wmOrtho2_pixelspace(context->region->winx / context->scale,
268 context->region->winy / context->scale);
269 uiBlock *block = UI_block_begin(context->C, context->region, __func__, UI_EMBOSS);
270
271 int channel_range[2];
272 displayed_channel_range_get(context, channel_range);
273
274 const float icon_width = icon_width_get(context);
275 const float offset_lock = icon_width * 1.5f;
276 const float offset_mute = icon_width * 2.5f;
277 const float offset_width = icon_width * 3.5f;
278 /* Draw widgets separately from text labels so they are batched together,
279 * instead of alternating between two fonts (regular and SVG/icons). */
280 for (int channel = channel_range[0]; channel <= channel_range[1]; channel++) {
281 draw_channel_widget_lock(context, block, channel, offset_lock);
282 draw_channel_widget_mute(context, block, channel, offset_mute);
283 }
284 for (int channel = channel_range[0]; channel <= channel_range[1]; channel++) {
285 draw_channel_labels(context, block, channel, offset_width);
286 }
287
288 UI_block_end(context->C, block);
289 UI_block_draw(context->C, block);
290
292}
293
294static void draw_background()
295{
297}
298
300 ARegion *region,
301 SeqChannelDrawContext *r_context)
302{
303 r_context->C = C;
304 r_context->area = CTX_wm_area(C);
305 r_context->region = region;
306 r_context->v2d = &region->v2d;
307 r_context->scene = CTX_data_scene(C);
308 r_context->ed = SEQ_editing_get(r_context->scene);
309 r_context->seqbase = SEQ_active_seqbase_get(r_context->ed);
310 r_context->channels = SEQ_channels_displayed_get(r_context->ed);
312 BLI_assert(r_context->timeline_region != nullptr);
313 r_context->timeline_region_v2d = &r_context->timeline_region->v2d;
314
317 r_context->draw_offset = draw_offset_get(r_context->timeline_region_v2d);
318
319 r_context->scale = min_ff(r_context->channel_height / (U.widget_unit * 0.6), 1);
320}
321
322void draw_channels(const bContext *C, ARegion *region)
323{
325
327 if (ed == nullptr) {
328 return;
329 }
330
331 SeqChannelDrawContext context;
332 channel_draw_context_init(C, region, &context);
333
334 if (round_fl_to_int(context.channel_height) == 0) {
335 return;
336 }
337
338 UI_view2d_view_ortho(context.v2d);
339
340 draw_channel_headers(&context);
341
343}
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
SpaceSeq * CTX_wm_space_seq(const bContext *C)
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:815
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition rct.c:408
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:197
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
#define CLAMP(a, b, c)
@ RGN_TYPE_WINDOW
void GPU_matrix_push()
void GPU_matrix_pop()
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
constexpr int SEQ_MAX_CHANNELS
@ UI_EMBOSS_NONE
@ UI_EMBOSS
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, const char *tip)
uiBut * uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, const char *tip)
const uiStyle * UI_style_get_dpi()
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss)
void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss)
void UI_block_draw(const bContext *C, uiBlock *block)
int int int UI_fontstyle_height_max(const uiFontStyle *fs)
bool UI_but_active_only(const bContext *C, ARegion *region, uiBlock *block, uiBut *but)
@ UI_BTYPE_TOGGLE
@ UI_BTYPE_TEXT
@ UI_BTYPE_LABEL
uiBut * uiDefButR(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, const char *tip)
void UI_block_end(const bContext *C, uiBlock *block)
@ TH_BACK
void UI_ThemeClearColor(int colorid)
void UI_view2d_view_restore(const bContext *C)
Definition view2d.cc:1158
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition view2d.cc:1691
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1091
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition view2d.cc:1686
#define ND_SEQUENCER
Definition WM_types.hh:404
#define NC_SCENE
Definition WM_types.hh:345
unsigned int U
Definition btGjkEpa3.h:78
SeqTimelineChannel * SEQ_channel_get_by_index(const ListBase *channels, const int channel_index)
Definition channels.cc:61
bool SEQ_channel_is_locked(const SeqTimelineChannel *channel)
Definition channels.cc:77
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition channels.cc:23
bool SEQ_channel_is_muted(const SeqTimelineChannel *channel)
Definition channels.cc:82
char * SEQ_channel_name_get(ListBase *channels, const int channel_index)
Definition channels.cc:66
const char * label
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
PropertyRNA * RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
PropertyRNA * RNA_struct_name_property(const StructRNA *type)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
const char * RNA_property_identifier(const PropertyRNA *prop)
ListBase * SEQ_active_seqbase_get(const Editing *ed)
Definition sequencer.cc:416
Editing * SEQ_editing_get(const Scene *scene)
Definition sequencer.cc:262
void draw_channels(const bContext *C, ARegion *region)
static bool channel_is_being_renamed(const SpaceSeq *sseq, const int channel_index)
static float channel_index_y_min(const SeqChannelDrawContext *context, const int index)
static float channel_height_pixelspace_get(const View2D *timeline_region_v2d)
static float draw_channel_widget_mute(const SeqChannelDrawContext *context, uiBlock *block, const int channel_index, const float offset)
static void draw_channel_labels(const SeqChannelDrawContext *context, uiBlock *block, const int channel_index, const float used_width)
static float draw_channel_widget_lock(const SeqChannelDrawContext *context, uiBlock *block, const int channel_index, const float offset)
void channel_draw_context_init(const bContext *C, ARegion *region, SeqChannelDrawContext *r_context)
static void draw_background()
static void displayed_channel_range_get(const SeqChannelDrawContext *context, int r_channel_range[2])
static float draw_offset_get(const View2D *timeline_region_v2d)
static std::string draw_channel_widget_tooltip(bContext *, void *argN, const char *)
static rctf label_rect_init(const SeqChannelDrawContext *context, const int channel_index, const float used_width)
static float widget_y_offset(const SeqChannelDrawContext *context)
static float frame_width_pixelspace_get(const View2D *timeline_region_v2d)
static void draw_channel_headers(const SeqChannelDrawContext *context)
static float icon_width_get(const SeqChannelDrawContext *context)
static float text_size_get(const SeqChannelDrawContext *context)
void SEQ_timeline_expand_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
StructRNA * type
Definition RNA_types.hh:41
SpaceSeq_Runtime * runtime
float xmax
float xmin
float ymax
float ymin
uiFontStyle widget
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
void wmOrtho2_pixelspace(const float x, const float y)