VSE: Scopes improvements #116798

Merged
Aras Pranckevicius merged 13 commits from aras_p/blender:vse-scopes into main 2024-01-05 22:03:13 +01:00
26 changed files with 812 additions and 875 deletions

View File

@ -34,6 +34,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
#include "DNA_view3d_types.h"

View File

@ -50,6 +50,7 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"

View File

@ -37,6 +37,7 @@
#include "DNA_pointcloud_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"

View File

@ -46,6 +46,7 @@
#include "DNA_modifier_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
#include "DNA_tracking_types.h"

View File

@ -46,6 +46,7 @@ set(SRC
sequencer_intern.hh
sequencer_quads_batch.hh
sequencer_scopes.hh
)
set(LIB
@ -73,6 +74,16 @@ if(WITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_TBB)
add_definitions(-DWITH_TBB)
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
)
list(APPEND LIB
${TBB_LIBRARIES}
)
endif()
blender_add_lib(bf_editor_space_sequencer "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -179,7 +179,7 @@ static float draw_channel_widget_lock(const SeqChannelDrawContext *context,
static bool channel_is_being_renamed(const SpaceSeq *sseq, const int channel_index)
{
return sseq->runtime.rename_channel_index == channel_index;
return sseq->runtime->rename_channel_index == channel_index;
}
static float text_size_get(const SeqChannelDrawContext *context)
@ -250,7 +250,7 @@ static void draw_channel_labels(const SeqChannelDrawContext *context,
UI_block_emboss_set(block, UI_EMBOSS_NONE);
if (UI_but_active_only(context->C, context->region, block, but) == false) {
sseq->runtime.rename_channel_index = 0;
sseq->runtime->rename_channel_index = 0;
}
WM_event_add_notifier(context->C, NC_SCENE | ND_SEQUENCER, context->scene);

View File

@ -38,7 +38,7 @@ static int sequencer_rename_channel_invoke(bContext *C, wmOperator * /*op*/, con
channel_draw_context_init(C, CTX_wm_region(C), &context);
float mouse_y = UI_view2d_region_to_view_y(context.timeline_region_v2d, event->mval[1]);
sseq->runtime.rename_channel_index = mouse_y;
sseq->runtime->rename_channel_index = mouse_y;
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, CTX_data_scene(C));
return OPERATOR_FINISHED;
}

View File

@ -8,11 +8,14 @@
#pragma once
#include "BLI_utility_mixins.hh"
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
#include "DNA_sequence_types.h"
#include "RNA_access.hh"
#include "sequencer_scopes.hh"
/* Internal exports only. */
class SeqQuadsBatch;
@ -40,6 +43,24 @@ struct ListBase;
#define DEFAULT_IMG_STRIP_LENGTH 25 /* XXX arbitrary but ok for now. */
#define OVERLAP_ALPHA 180
namespace blender::ed::seq {
struct SpaceSeq_Runtime : public NonCopyable {
/** Required for Thumbnail job start condition. */
rctf last_thumbnail_area = {0, 0, 0, 0};
/** Stores lists of most recently displayed thumbnails. */
GHash *last_displayed_thumbnails = nullptr;
int rename_channel_index = 0;
float timeline_clamp_custom_range = 0;
blender::ed::seq::SeqScopes scopes;
aras_p marked this conversation as resolved Outdated

BLI_utility_mixins.hh makes this a bit nicer, with NonCopyable

`BLI_utility_mixins.hh` makes this a bit nicer, with `NonCopyable`
SpaceSeq_Runtime() = default;
~SpaceSeq_Runtime();
};
} // namespace blender::ed::seq
struct SeqChannelDrawContext {
const bContext *C;
ScrArea *area;
@ -258,14 +279,6 @@ void sequencer_dropboxes();
void sequencer_operatortypes();
void sequencer_keymap(wmKeyConfig *keyconf);
/* sequencer_scope.c */
ImBuf *make_waveform_view_from_ibuf(ImBuf *ibuf);
ImBuf *make_sep_waveform_view_from_ibuf(ImBuf *ibuf);
ImBuf *make_vectorscope_view_from_ibuf(ImBuf *ibuf);
ImBuf *make_zebra_view_from_ibuf(ImBuf *ibuf, float perc);
ImBuf *make_histogram_view_from_ibuf(ImBuf *ibuf);
/* `sequencer_buttons.cc` */
void sequencer_buttons_register(ARegionType *art);

View File

@ -9,7 +9,10 @@
#include <cmath>
#include <cstring>
#include "BLF_api.h"
#include "BLI_blenlib.h"
#include "BLI_math_rotation.h"
#include "BLI_utildefines.h"
#include "IMB_imbuf_types.h"
@ -56,8 +59,9 @@
#include "WM_api.hh"
#include "WM_types.hh"
/* Own include. */
#include "sequencer_intern.hh"
#include "sequencer_quads_batch.hh"
#include "sequencer_scopes.hh"
static Sequence *special_seq_update = nullptr;
@ -158,37 +162,9 @@ ImBuf *sequencer_ibuf_get(Main *bmain,
return ibuf;
}
static void sequencer_check_scopes(SequencerScopes *scopes, ImBuf *ibuf)
{
if (scopes->reference_ibuf != ibuf) {
if (scopes->zebra_ibuf) {
IMB_freeImBuf(scopes->zebra_ibuf);
scopes->zebra_ibuf = nullptr;
}
if (scopes->waveform_ibuf) {
IMB_freeImBuf(scopes->waveform_ibuf);
scopes->waveform_ibuf = nullptr;
}
if (scopes->sep_waveform_ibuf) {
IMB_freeImBuf(scopes->sep_waveform_ibuf);
scopes->sep_waveform_ibuf = nullptr;
}
if (scopes->vector_ibuf) {
IMB_freeImBuf(scopes->vector_ibuf);
scopes->vector_ibuf = nullptr;
}
if (scopes->histogram_ibuf) {
IMB_freeImBuf(scopes->histogram_ibuf);
scopes->histogram_ibuf = nullptr;
}
}
}
static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_fn)(ImBuf *ibuf))
static ImBuf *sequencer_make_scope(Scene *scene,
ImBuf *ibuf,
ImBuf *(*make_scope_fn)(const ImBuf *ibuf))
{
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
ImBuf *scope;
@ -451,11 +427,9 @@ static void sequencer_draw_display_buffer(const bContext *C,
ARegion *region,
SpaceSeq *sseq,
ImBuf *ibuf,
ImBuf *scope,
bool draw_overlay,
bool draw_backdrop)
{
void *display_buffer;
void *buffer_cache_handle = nullptr;
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
@ -472,21 +446,8 @@ static void sequencer_draw_display_buffer(const bContext *C,
uint texCoord = GPU_vertformat_attr_add(
imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (scope) {
ibuf = scope;
if (ibuf->float_buffer.data && ibuf->byte_buffer.data == nullptr) {
IMB_rect_from_float(ibuf);
}
display_buffer = ibuf->byte_buffer.data;
format = GPU_RGBA8;
data = GPU_DATA_UBYTE;
}
else {
display_buffer = sequencer_OCIO_transform_ibuf(
C, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
}
void *display_buffer = sequencer_OCIO_transform_ibuf(
C, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
if (draw_backdrop) {
GPU_matrix_push();
@ -558,68 +519,350 @@ static void sequencer_draw_display_buffer(const bContext *C,
}
}
static ImBuf *sequencer_get_scope(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf, bool draw_backdrop)
static void draw_histogram(ARegion *region,
const blender::ed::seq::ScopeHistogram &hist,
SeqQuadsBatch &quads,
const rctf &area)
{
ImBuf *scope = nullptr;
SequencerScopes *scopes = &sseq->scopes;
using namespace blender::ed::seq;
if (hist.data.is_empty()) {
return;
}
if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
sequencer_check_scopes(scopes, ibuf);
/* Background. */
uchar col_bg[4] = {0, 0, 0, 255};
quads.add_quad(area.xmin, area.ymin, area.xmax, area.ymax, col_bg);
switch (sseq->mainb) {
case SEQ_DRAW_IMG_IMBUF:
if (!scopes->zebra_ibuf) {
/* Grid lines and labels. */
uchar col_grid[4] = {128, 128, 128, 128};
float grid_x_0 = area.xmin;
float grid_x_1 = area.xmax;
/* Float histograms show more than 0..1 range horizontally. */
aras_p marked this conversation as resolved Outdated

This looks a little bit cursed, along with (0.25f / 1.5f). It wasn't obvious to me, that float images do use 512 wide array and that this oversaples the image. Can you clarify this in a comment?

This looks a little bit cursed, along with `(0.25f / 1.5f)`. It wasn't obvious to me, that float images do use 512 wide array and that this oversaples the image. Can you clarify this in a comment?

Good point, will add named constants for these things

Good point, will add named constants for these things
if (hist.is_float_hist()) {
float ratio_0 = ratiof(ScopeHistogram::FLOAT_VAL_MIN, ScopeHistogram::FLOAT_VAL_MAX, 0.0f);
float ratio_1 = ratiof(ScopeHistogram::FLOAT_VAL_MIN, ScopeHistogram::FLOAT_VAL_MAX, 1.0f);
grid_x_0 = area.xmin + (area.xmax - area.xmin) * ratio_0;
grid_x_1 = area.xmin + (area.xmax - area.xmin) * ratio_1;
}
aras_p marked this conversation as resolved Outdated

You can use UI_view2d_scale_get_x() here

You can use `UI_view2d_scale_get_x()` here
if (ibuf->float_buffer.data) {
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
IMB_colormanagement_imbuf_make_display_space(
display_ibuf, &scene->view_settings, &scene->display_settings);
scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
IMB_freeImBuf(display_ibuf);
}
else {
scopes->zebra_ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
}
}
scope = scopes->zebra_ibuf;
break;
case SEQ_DRAW_IMG_WAVEFORM:
if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
if (!scopes->sep_waveform_ibuf) {
scopes->sep_waveform_ibuf = sequencer_make_scope(
scene, ibuf, make_sep_waveform_view_from_ibuf);
}
scope = scopes->sep_waveform_ibuf;
}
else {
if (!scopes->waveform_ibuf) {
scopes->waveform_ibuf = sequencer_make_scope(
scene, ibuf, make_waveform_view_from_ibuf);
}
scope = scopes->waveform_ibuf;
}
break;
case SEQ_DRAW_IMG_VECTORSCOPE:
if (!scopes->vector_ibuf) {
scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
}
scope = scopes->vector_ibuf;
break;
case SEQ_DRAW_IMG_HISTOGRAM:
if (!scopes->histogram_ibuf) {
scopes->histogram_ibuf = sequencer_make_scope(
scene, ibuf, make_histogram_view_from_ibuf);
}
scope = scopes->histogram_ibuf;
break;
View2D *v2d = &region->v2d;
float text_scale_x, text_scale_y;
UI_view2d_scale_get_inverse(v2d, &text_scale_x, &text_scale_y);
for (int line = 0; line <= 4; line++) {
float val = float(line) / 4;
float x = grid_x_0 + (grid_x_1 - grid_x_0) * val;
quads.add_line(x, area.ymin, x, area.ymax, col_grid);
aras_p marked this conversation as resolved
Review

Use BLI_snprintf()

Use `BLI_snprintf()`
/* Label. */
char buf[10];
BLI_snprintf(buf, sizeof(buf), "%.2f", val);
size_t buf_len = strlen(buf);
float text_width, text_height;
BLF_width_and_height(BLF_default(), buf, buf_len, &text_width, &text_height);
text_width *= text_scale_x;
text_height *= text_scale_y;
UI_view2d_text_cache_add(
v2d, x - text_width / 2, area.ymax - text_height * 1.3f, buf, buf_len, col_grid);
}
/* Border. */
uchar col_border[4] = {64, 64, 64, 128};
quads.add_wire_quad(area.xmin, area.ymin, area.xmax, area.ymax, col_border);
/* Histogram area & line for each R/G/B channels, additively blended. */
quads.draw();
GPU_blend(GPU_BLEND_ADDITIVE);
for (int ch = 0; ch < 3; ++ch) {
if (hist.max_value[ch] == 0) {
continue;
}
uchar col_line[4] = {32, 32, 32, 255};
uchar col_area[4] = {64, 64, 64, 128};
col_line[ch] = 224;
col_area[ch] = 224;
float y_scale = (area.ymax - area.ymin) / hist.max_value[ch] * 0.95f;
float x_scale = (area.xmax - area.xmin) / hist.data.size();
float yb = area.ymin;
for (int bin = 0; bin < hist.data.size() - 1; bin++) {
float x0 = area.xmin + (bin + 0.5f) * x_scale;
float x1 = area.xmin + (bin + 1.5f) * x_scale;
/* Future files may have new scopes we don't catch above. */
if (scope) {
scopes->reference_ibuf = ibuf;
float y0 = area.ymin + hist.data[bin][ch] * y_scale;
float y1 = area.ymin + hist.data[bin + 1][ch] * y_scale;
quads.add_quad(x0, yb, x0, y0, x1, yb, x1, y1, col_area);
quads.add_line(x0, y0, x1, y1, col_line);
}
}
return scope;
quads.draw();
GPU_blend(GPU_BLEND_ALPHA);
UI_view2d_text_cache_draw(region);
}
static blender::float2 rgb_to_uv(const blender::float3 &rgb)
{
float y, u, v;
rgb_to_yuv(rgb.x, rgb.y, rgb.z, &y, &u, &v, BLI_YUV_ITU_BT709);
return blender::float2(u, v);
}
static void draw_waveform_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
{
/* Horizontal lines at 10%, 70%, 90%. */
const float lines[3] = {0.1f, 0.7f, 0.9f};
uchar col_grid[4] = {160, 64, 64, 128};
const float x0 = area.xmin;
const float x1 = area.xmax;
for (int i = 0; i < 3; i++) {
aras_p marked this conversation as resolved
Review

Use BLI_snprintf()

Use `BLI_snprintf()`
const float y = area.ymin + (area.ymax - area.ymin) * lines[i];
char buf[10];
BLI_snprintf(buf, sizeof(buf), "%.1f", lines[i]);
quads.add_line(x0, y, x1, y, col_grid);
UI_view2d_text_cache_add(&region->v2d, x0 + 8, y + 8, buf, strlen(buf), col_grid);
}
/* Border. */
uchar col_border[4] = {64, 64, 64, 128};
quads.add_wire_quad(x0, area.ymin, x1, area.ymax, col_border);
quads.draw();
UI_view2d_text_cache_draw(region);
}
static void draw_vectorscope_graticule(SeqQuadsBatch &quads, const rctf &area)
{
using namespace blender;
GPU_blend(GPU_BLEND_ALPHA);
const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
const float w = BLI_rctf_size_x(&area);
const float h = BLI_rctf_size_y(&area);
const float centerx = BLI_rctf_cent_x(&area);
const float centery = BLI_rctf_cent_y(&area);
const float rad_base = ((w < h) ? w : h) * 0.5f;
/* vectorscope image is scaled over YUV range, +/- (0.436, 0.615) */
const float rad_x = rad_base * (0.5f / 0.436f);
const float rad_y = rad_base * (0.5f / 0.615f);
/* center cross */
uchar col_grid[4] = {128, 128, 128, 96};
quads.add_line(centerx - rad_base * 0.1f, centery, centerx + rad_base * 0.1f, centery, col_grid);
quads.add_line(centerx, centery - rad_base * 0.1f, centerx, centery + rad_base * 0.1f, col_grid);
/* fully saturated vs "safe" (0.75) colored areas */
const float3 primaries[6] = {
{1, 0, 0},
{1, 1, 0},
{0, 1, 0},
{0, 1, 1},
{0, 0, 1},
{1, 0, 1},
};
float2 center{centerx, centery};
float2 rad_scale{rad_x * 2, rad_y * 2};
for (int i = 0; i < 6; i++) {
float3 prim0 = primaries[i];
float3 prim1 = primaries[(i + 1) % 6];
float3 safe0 = prim0 * 0.75f;
float3 safe1 = prim1 * 0.75f;
float2 uv0 = center + rgb_to_uv(prim0) * rad_scale;
float2 uv1 = center + rgb_to_uv(prim1) * rad_scale;
float2 uv2 = center + rgb_to_uv(safe0) * rad_scale;
float2 uv3 = center + rgb_to_uv(safe1) * rad_scale;
uchar col0[4] = {uchar(prim0.x * 255), uchar(prim0.y * 255), uchar(prim0.z * 255), 64};
uchar col1[4] = {uchar(prim1.x * 255), uchar(prim1.y * 255), uchar(prim1.z * 255), 64};
uchar col2[4] = {uchar(safe0.x * 255), uchar(safe0.y * 255), uchar(safe0.z * 255), 64};
uchar col3[4] = {uchar(safe1.x * 255), uchar(safe1.y * 255), uchar(safe1.z * 255), 64};
quads.add_quad(uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y, uv3.x, uv3.y, col0, col1, col2, col3);
col0[3] = col1[3] = col2[3] = col3[3] = 192;
quads.add_line(uv0.x, uv0.y, uv1.x, uv1.y, col0, col1);
quads.add_line(uv2.x, uv2.y, uv3.x, uv3.y, col2, col3);
}
aras_p marked this conversation as resolved Outdated

I mean, it is a solution :) Just to be clear, no need to do anything about this, just wanted to say, that I laughed a bit.
Eh actually, I noticed a missing full stop at the comment, so that should be fixed.

I mean, it is a solution :) Just to be clear, no need to do anything about this, just wanted to say, that I laughed a bit. Eh actually, I noticed a missing full stop at the comment, so that should be fixed.
/* skin tone line */
uchar col_tone[4] = {255, 102, 0, 128};
const float tone_line_len = 0.895f; /* makes it end at outer edge of saturation ring. */
quads.add_line(centerx,
centery,
centerx + cosf(skin_rad) * rad_x * tone_line_len,
centery + sinf(skin_rad) * rad_y * tone_line_len,
col_tone);
}
static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
{
using namespace blender::ed::seq;
/* Figure out draw coordinates. */
rctf preview;
sequencer_preview_get_rect(&preview, scene, region, sseq, false, false);
aras_p marked this conversation as resolved Outdated

I am bit lost here, why do you need overlay rect for scope?

I am bit lost here, why do you need overlay rect for scope?

Nice catch! I don't.

Nice catch! I don't.
rctf uv;
BLI_rctf_init(&uv, 0.0f, 1.0f, 0.0f, 1.0f);
const bool keep_aspect = sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE;
float vecscope_aspect = 1.0f;
if (keep_aspect) {
float width = std::max(BLI_rctf_size_x(&preview), 0.1f);
float height = std::max(BLI_rctf_size_y(&preview), 0.1f);
vecscope_aspect = width / height;
if (vecscope_aspect >= 1.0f) {
BLI_rctf_resize_x(&uv, vecscope_aspect);
}
else {
BLI_rctf_resize_y(&uv, 1.0f / vecscope_aspect);
}
}
SeqQuadsBatch quads;
SeqScopes *scopes = &sseq->runtime->scopes;
/* Draw scope image if there is one. */
bool use_blend = sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA;
ImBuf *scope_image = nullptr;
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
scope_image = scopes->zebra_ibuf;
}
else if (sseq->mainb == SEQ_DRAW_IMG_WAVEFORM) {
scope_image = (sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0 ? scopes->sep_waveform_ibuf :
scopes->waveform_ibuf;
}
else if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
scope_image = scopes->vector_ibuf;
}
else if (sseq->mainb == SEQ_DRAW_IMG_HISTOGRAM) {
use_blend = true;
}
if (use_blend) {
GPU_blend(GPU_BLEND_ALPHA);
}
if (scope_image != nullptr) {
if (scope_image->float_buffer.data && scope_image->byte_buffer.data == nullptr) {
IMB_rect_from_float(scope_image);
}
eGPUTextureFormat format = GPU_RGBA8;
eGPUDataFormat data = GPU_DATA_UBYTE;
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT;
GPUTexture *texture = GPU_texture_create_2d(
"seq_display_buf", scope_image->x, scope_image->y, 1, format, usage, nullptr);
GPU_texture_update(texture, data, scope_image->byte_buffer.data);
GPU_texture_filter_mode(texture, false);
GPU_texture_extend_mode(texture, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_bind(texture, 0);
GPUVertFormat *imm_format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
uint texCoord = GPU_vertformat_attr_add(
imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR);
immUniformColor3f(1.0f, 1.0f, 1.0f);
immBegin(GPU_PRIM_TRI_FAN, 4);
immAttr2f(texCoord, uv.xmin, uv.ymin);
immVertex2f(pos, preview.xmin, preview.ymin);
immAttr2f(texCoord, uv.xmin, uv.ymax);
immVertex2f(pos, preview.xmin, preview.ymax);
immAttr2f(texCoord, uv.xmax, uv.ymax);
immVertex2f(pos, preview.xmax, preview.ymax);
immAttr2f(texCoord, uv.xmax, uv.ymin);
immVertex2f(pos, preview.xmax, preview.ymin);
immEnd();
GPU_texture_unbind(texture);
GPU_texture_free(texture);
immUnbindProgram();
}
if (sseq->mainb == SEQ_DRAW_IMG_HISTOGRAM) {
draw_histogram(region, scopes->histogram, quads, preview);
}
if (sseq->mainb == SEQ_DRAW_IMG_WAVEFORM) {
use_blend = true;
draw_waveform_graticule(region, quads, preview);
}
if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
use_blend = true;
draw_vectorscope_graticule(quads, preview);
}
quads.draw();
if (use_blend) {
GPU_blend(GPU_BLEND_NONE);
}
}
static bool sequencer_calc_scopes(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf, bool draw_backdrop)
{
using namespace blender::ed::seq;
if (draw_backdrop || (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->zebra == 0)) {
return false; /* Not drawing any scopes. */
}
SeqScopes *scopes = &sseq->runtime->scopes;
if (scopes->reference_ibuf != ibuf) {
scopes->cleanup();
}
switch (sseq->mainb) {
case SEQ_DRAW_IMG_IMBUF:
if (!scopes->zebra_ibuf) {
if (ibuf->float_buffer.data) {
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
IMB_colormanagement_imbuf_make_display_space(
display_ibuf, &scene->view_settings, &scene->display_settings);
scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
IMB_freeImBuf(display_ibuf);
}
else {
scopes->zebra_ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
}
}
break;
case SEQ_DRAW_IMG_WAVEFORM:
if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
if (!scopes->sep_waveform_ibuf) {
scopes->sep_waveform_ibuf = sequencer_make_scope(
scene, ibuf, make_sep_waveform_view_from_ibuf);
}
}
else {
if (!scopes->waveform_ibuf) {
scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
}
}
break;
case SEQ_DRAW_IMG_VECTORSCOPE:
if (!scopes->vector_ibuf) {
scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
}
break;
case SEQ_DRAW_IMG_HISTOGRAM: {
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
IMB_colormanagement_imbuf_make_display_space(
display_ibuf, &scene->view_settings, &scene->display_settings);
scopes->histogram.calc_from_ibuf(display_ibuf);
IMB_freeImBuf(display_ibuf);
} break;
default: /* Future files might have scopes we don't know about. */
return false;
}
scopes->reference_ibuf = ibuf;
return true;
}
bool sequencer_draw_get_transform_preview(SpaceSeq *sseq, Scene *scene)
@ -732,7 +975,6 @@ void sequencer_draw_preview(const bContext *C,
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
View2D *v2d = &region->v2d;
ImBuf *ibuf = nullptr;
ImBuf *scope = nullptr;
float viewrect[2];
const bool show_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
const bool draw_gpencil = ((sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_GPENCIL) && sseq->gpd);
@ -781,13 +1023,17 @@ void sequencer_draw_preview(const bContext *C,
}
if (ibuf) {
scope = sequencer_get_scope(scene, sseq, ibuf, draw_backdrop);
bool has_scope = sequencer_calc_scopes(scene, sseq, ibuf, draw_backdrop);
if (has_scope) {
/* Draw scope. */
sequencer_draw_scopes(scene, region, sseq);
}
else {
/* Draw image. */
sequencer_draw_display_buffer(C, scene, region, sseq, ibuf, draw_overlay, draw_backdrop);
}
/* Draw image. */
sequencer_draw_display_buffer(
C, scene, region, sseq, ibuf, scope, draw_overlay, draw_backdrop);
/* Draw over image. */
/* Draw metadata. */
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_METADATA && sseq->flag & SEQ_SHOW_OVERLAY) {
ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
}
@ -821,7 +1067,6 @@ void sequencer_draw_preview(const bContext *C,
ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
/* Scope is freed in sequencer_check_scopes when `ibuf` changes and redraw is needed. */
if (ibuf) {
IMB_freeImBuf(ibuf);
}

View File

@ -53,10 +53,10 @@ SeqQuadsBatch::SeqQuadsBatch()
batch_quads = GPU_batch_create_ex(
GPU_PRIM_TRIS, vbo_quads, ibo_quads, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
GPU_batch_program_set_builtin(batch_quads, GPU_SHADER_3D_FLAT_COLOR);
GPU_batch_program_set_builtin(batch_quads, GPU_SHADER_3D_SMOOTH_COLOR);
batch_lines = GPU_batch_create_ex(GPU_PRIM_LINES, vbo_lines, nullptr, GPU_BATCH_OWNS_VBO);
GPU_batch_program_set_builtin(batch_lines, GPU_SHADER_3D_FLAT_COLOR);
GPU_batch_program_set_builtin(batch_lines, GPU_SHADER_3D_SMOOTH_COLOR);
}
SeqQuadsBatch::~SeqQuadsBatch()
@ -93,7 +93,10 @@ void SeqQuadsBatch::add_quad(float x1,
float y3,
float x4,
float y4,
const uchar color[4])
const uchar color1[4],
const uchar color2[4],
const uchar color3[4],
const uchar color4[4])
{
if (quads_num >= MAX_QUADS) {
draw();
@ -103,10 +106,10 @@ void SeqQuadsBatch::add_quad(float x1,
BLI_assert(verts_quads != nullptr);
}
ColorVertex v0 = {blender::float2(x1, y1), color};
ColorVertex v1 = {blender::float2(x2, y2), color};
ColorVertex v2 = {blender::float2(x3, y3), color};
ColorVertex v3 = {blender::float2(x4, y4), color};
ColorVertex v0 = {blender::float2(x1, y1), color1};
ColorVertex v1 = {blender::float2(x2, y2), color2};
ColorVertex v2 = {blender::float2(x3, y3), color3};
ColorVertex v3 = {blender::float2(x4, y4), color4};
*verts_quads++ = v0;
*verts_quads++ = v1;
@ -147,7 +150,8 @@ void SeqQuadsBatch::add_wire_quad(float x1, float y1, float x2, float y2, const
lines_num += 4;
}
void SeqQuadsBatch::add_line(float x1, float y1, float x2, float y2, const uchar color[4])
void SeqQuadsBatch::add_line(
float x1, float y1, float x2, float y2, const uchar color1[4], const uchar color2[4])
{
if (lines_num + 1 > MAX_LINES) {
draw();
@ -157,8 +161,8 @@ void SeqQuadsBatch::add_line(float x1, float y1, float x2, float y2, const uchar
BLI_assert(verts_lines != nullptr);
}
ColorVertex v0 = {blender::float2(x1, y1), color};
ColorVertex v1 = {blender::float2(x2, y2), color};
ColorVertex v0 = {blender::float2(x1, y1), color1};
ColorVertex v1 = {blender::float2(x2, y2), color2};
*verts_lines++ = v0;
*verts_lines++ = v1;

View File

@ -33,9 +33,9 @@ class SeqQuadsBatch {
/** Add an axis-aligned quad. */
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
{
add_quad(x1, y1, x1, y2, x2, y1, x2, y2, color);
add_quad(x1, y1, x1, y2, x2, y1, x2, y2, color, color, color, color);
}
/** Add a quad. */
/** Add a quad with four arbitrary coordinates and one color. */
void add_quad(float x1,
float y1,
float x2,
@ -44,11 +44,33 @@ class SeqQuadsBatch {
float y3,
float x4,
float y4,
const uchar color[4]);
const uchar color[4])
{
add_quad(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
}
/** Add a quad with four arbitrary coordinates and a color for each. */
void add_quad(float x1,
float y1,
float x2,
float y2,
float x3,
float y3,
float x4,
float y4,
const uchar color1[4],
const uchar color2[4],
const uchar color3[4],
const uchar color4[4]);
/** Add four lines of an axis-aligned quad edges. */
void add_wire_quad(float x1, float y1, float x2, float y2, const uchar color[4]);
/** Add a line. */
void add_line(float x1, float y1, float x2, float y2, const uchar color[4]);
/** Add a line with single color. */
void add_line(float x1, float y1, float x2, float y2, const uchar color[4])
{
add_line(x1, y1, x2, y2, color, color);
}
/** Add a line with two endpoint colors. */
void add_line(
float x1, float y1, float x2, float y2, const uchar color1[4], const uchar color2[4]);
private:
static constexpr int MAX_QUADS = 1024;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spseq
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_utility_mixins.hh"
struct ImBuf;
namespace blender::ed::seq {
struct ScopeHistogram {
/* Byte images just have bins for the 0..255 range. */
static constexpr int BINS_BYTE = 256;
/* Float images spead -0.25..+1.25 range over 512 bins. */
static constexpr int BINS_FLOAT = 512;
static constexpr float FLOAT_VAL_MIN = -0.25f;
static constexpr float FLOAT_VAL_MAX = 1.25f;
Array<uint3> data;
uint3 max_value;
void calc_from_ibuf(const ImBuf *ibuf);
bool is_float_hist() const
{
return data.size() == BINS_FLOAT;
}
aras_p marked this conversation as resolved Outdated

The style guide mentions putting member variables before method declarations, might as well stay consistent

The style guide mentions putting member variables before method declarations, might as well stay consistent
};
struct SeqScopes : public NonCopyable {
ImBuf *reference_ibuf = nullptr;
ImBuf *zebra_ibuf = nullptr;
ImBuf *waveform_ibuf = nullptr;
ImBuf *sep_waveform_ibuf = nullptr;
ImBuf *vector_ibuf = nullptr;
ScopeHistogram histogram;
SeqScopes() = default;
~SeqScopes();
void cleanup();
};
ImBuf *make_waveform_view_from_ibuf(const ImBuf *ibuf);
ImBuf *make_sep_waveform_view_from_ibuf(const ImBuf *ibuf);
ImBuf *make_vectorscope_view_from_ibuf(const ImBuf *ibuf);
ImBuf *make_zebra_view_from_ibuf(const ImBuf *ibuf, float perc);
} // namespace blender::ed::seq

View File

@ -295,21 +295,21 @@ static void sequencer_thumbnail_start_job_if_necessary(
/* Job start requested, but over area which has been processed. Unless `thumbnail_is_missing` is
* true, ignore this request as all images are in view. */
if (v2d->cur.xmax == sseq->runtime.last_thumbnail_area.xmax &&
v2d->cur.ymax == sseq->runtime.last_thumbnail_area.ymax && !thumbnail_is_missing)
if (v2d->cur.xmax == sseq->runtime->last_thumbnail_area.xmax &&
v2d->cur.ymax == sseq->runtime->last_thumbnail_area.ymax && !thumbnail_is_missing)
{
return;
}
/* Stop the job first as view has changed. Pointless to continue old job. */
if (v2d->cur.xmax != sseq->runtime.last_thumbnail_area.xmax ||
v2d->cur.ymax != sseq->runtime.last_thumbnail_area.ymax)
if (v2d->cur.xmax != sseq->runtime->last_thumbnail_area.xmax ||
v2d->cur.ymax != sseq->runtime->last_thumbnail_area.ymax)
{
WM_jobs_stop(CTX_wm_manager(C), nullptr, thumbnail_start_job);
}
sequencer_thumbnail_init_job(C, v2d, ed, thumb_height);
sseq->runtime.last_thumbnail_area = v2d->cur;
sseq->runtime->last_thumbnail_area = v2d->cur;
}
void last_displayed_thumbnails_list_free(void *val)
@ -320,15 +320,15 @@ void last_displayed_thumbnails_list_free(void *val)
static GSet *last_displayed_thumbnails_list_ensure(const bContext *C, Sequence *seq)
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
if (sseq->runtime.last_displayed_thumbnails == nullptr) {
sseq->runtime.last_displayed_thumbnails = BLI_ghash_ptr_new(__func__);
if (sseq->runtime->last_displayed_thumbnails == nullptr) {
sseq->runtime->last_displayed_thumbnails = BLI_ghash_ptr_new(__func__);
}
GSet *displayed_thumbnails = static_cast<GSet *>(
BLI_ghash_lookup(sseq->runtime.last_displayed_thumbnails, seq));
BLI_ghash_lookup(sseq->runtime->last_displayed_thumbnails, seq));
if (displayed_thumbnails == nullptr) {
displayed_thumbnails = BLI_gset_int_new(__func__);
BLI_ghash_insert(sseq->runtime.last_displayed_thumbnails, seq, displayed_thumbnails);
BLI_ghash_insert(sseq->runtime->last_displayed_thumbnails, seq, displayed_thumbnails);
}
return displayed_thumbnails;

View File

@ -62,8 +62,15 @@
static void sequencer_scopes_tag_refresh(ScrArea *area)
{
SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
sseq->runtime->scopes.reference_ibuf = nullptr;
}
sseq->scopes.reference_ibuf = nullptr;
blender::ed::seq::SpaceSeq_Runtime::~SpaceSeq_Runtime()
{
if (last_displayed_thumbnails != nullptr) {
BLI_ghash_free(last_displayed_thumbnails, nullptr, last_displayed_thumbnails_list_free);
last_displayed_thumbnails = nullptr;
}
}
/* ******************** manage regions ********************* */
@ -98,9 +105,6 @@ static SpaceLink *sequencer_create(const ScrArea * /*area*/, const Scene *scene)
SEQ_TIMELINE_SHOW_FCURVES | SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG |
SEQ_TIMELINE_SHOW_STRIP_RETIMING | SEQ_TIMELINE_ALL_WAVEFORMS;
BLI_rctf_init(&sseq->runtime.last_thumbnail_area, 0.0f, 0.0f, 0.0f, 0.0f);
sseq->runtime.last_displayed_thumbnails = nullptr;
/* Header. */
region = MEM_cnew<ARegion>("header for sequencer");
@ -192,8 +196,6 @@ static SpaceLink *sequencer_create(const ScrArea * /*area*/, const Scene *scene)
region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
region->v2d.align = V2D_ALIGN_NO_NEG_Y;
sseq->runtime.last_displayed_thumbnails = nullptr;
return (SpaceLink *)sseq;
}
@ -201,43 +203,23 @@ static SpaceLink *sequencer_create(const ScrArea * /*area*/, const Scene *scene)
static void sequencer_free(SpaceLink *sl)
{
SpaceSeq *sseq = (SpaceSeq *)sl;
SequencerScopes *scopes = &sseq->scopes;
MEM_delete(sseq->runtime);
#if 0
if (sseq->gpd) {
BKE_gpencil_free_data(sseq->gpd);
}
#endif
if (scopes->zebra_ibuf) {
IMB_freeImBuf(scopes->zebra_ibuf);
}
if (scopes->waveform_ibuf) {
IMB_freeImBuf(scopes->waveform_ibuf);
}
if (scopes->sep_waveform_ibuf) {
IMB_freeImBuf(scopes->sep_waveform_ibuf);
}
if (scopes->vector_ibuf) {
IMB_freeImBuf(scopes->vector_ibuf);
}
if (scopes->histogram_ibuf) {
IMB_freeImBuf(scopes->histogram_ibuf);
}
if (sseq->runtime.last_displayed_thumbnails) {
BLI_ghash_free(
sseq->runtime.last_displayed_thumbnails, nullptr, last_displayed_thumbnails_list_free);
sseq->runtime.last_displayed_thumbnails = nullptr;
}
}
/* Space-type init callback. */
static void sequencer_init(wmWindowManager * /*wm*/, ScrArea * /*area*/) {}
static void sequencer_init(wmWindowManager * /*wm*/, ScrArea *area)
{
SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
if (sseq->runtime == nullptr) {
sseq->runtime = MEM_new<SpaceSeq_Runtime>(__func__);
}
}
static void sequencer_refresh(const bContext *C, ScrArea *area)
{
@ -301,13 +283,11 @@ static void sequencer_refresh(const bContext *C, ScrArea *area)
static SpaceLink *sequencer_duplicate(SpaceLink *sl)
{
SpaceSeq *sseqn = static_cast<SpaceSeq *>(MEM_dupallocN(sl));
sseqn->runtime = MEM_new<SpaceSeq_Runtime>(__func__);
/* Clear or remove stuff from old. */
// sseq->gpd = gpencil_data_duplicate(sseq->gpd, false);
memset(&sseqn->scopes, 0, sizeof(sseqn->scopes));
memset(&sseqn->runtime, 0, sizeof(sseqn->runtime));
return (SpaceLink *)sseqn;
}
@ -534,7 +514,7 @@ static void sequencer_main_clamp_view(const bContext *C, ARegion *region)
}
/* If strip is deleted, don't move view automatically, keep current range until it is changed. */
strip_boundbox.ymax = max_ff(sseq->runtime.timeline_clamp_custom_range, strip_boundbox.ymax);
strip_boundbox.ymax = max_ff(sseq->runtime->timeline_clamp_custom_range, strip_boundbox.ymax);
rctf view_clamped = v2d->cur;
@ -557,7 +537,7 @@ static void sequencer_main_region_clamp_custom_set(const bContext *C, ARegion *r
View2D *v2d = &region->v2d;
if ((v2d->flag & V2D_IS_NAVIGATING) == 0) {
sseq->runtime.timeline_clamp_custom_range = v2d->cur.ymax;
sseq->runtime->timeline_clamp_custom_range = v2d->cur.ymax;
}
}
@ -960,6 +940,8 @@ static void sequencer_space_blend_read_data(BlendDataReader * /*reader*/, SpaceL
{
SpaceSeq *sseq = (SpaceSeq *)sl;
sseq->runtime = nullptr;
/* grease pencil data is not a direct data and can't be linked from direct_link*
* functions, it should be linked from lib_link* functions instead
*
@ -973,13 +955,6 @@ static void sequencer_space_blend_read_data(BlendDataReader * /*reader*/, SpaceL
BKE_gpencil_blend_read_data(fd, sseq->gpd);
}
#endif
sseq->scopes.reference_ibuf = nullptr;
sseq->scopes.zebra_ibuf = nullptr;
sseq->scopes.waveform_ibuf = nullptr;
sseq->scopes.sep_waveform_ibuf = nullptr;
sseq->scopes.vector_ibuf = nullptr;
sseq->scopes.histogram_ibuf = nullptr;
memset(&sseq->runtime, 0x0, sizeof(sseq->runtime));
}
static void sequencer_space_blend_write(BlendWriter *writer, SpaceLink *sl)

View File

@ -6,6 +6,7 @@
* \ingroup edtransform
*/
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"

View File

@ -8,6 +8,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "BLI_listbase.h"

View File

@ -8,6 +8,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "BLI_listbase.h"

View File

@ -19,6 +19,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"

View File

@ -14,6 +14,8 @@
#include "BKE_context.hh"
#include "DNA_sequence_types.h"
#include "ED_screen.hh"
#include "ED_transform.hh"

View File

@ -16,6 +16,7 @@
#include "DNA_image_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "IMB_filetype.h"

View File

@ -545,19 +545,9 @@ typedef struct SoundEqualizerModifierData {
/** \} */
/* -------------------------------------------------------------------- */
/** \name Scopes
/** \name Flags & Types
* \{ */
typedef struct SequencerScopes {
struct ImBuf *reference_ibuf;
struct ImBuf *zebra_ibuf;
struct ImBuf *waveform_ibuf;
struct ImBuf *sep_waveform_ibuf;
struct ImBuf *vector_ibuf;
struct ImBuf *histogram_ibuf;
} SequencerScopes;
#define MAXSEQ 128
/** #Editor::overlay_frame_flag */
@ -583,12 +573,6 @@ enum {
SEQ_SPEED_USE_INTERPOLATION = 1 << 3,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Flags & Types
* \{ */
#define SEQ_NAME_MAXSTR 64
/* From: `DNA_object_types.h`, see it's doc-string there. */

View File

@ -19,7 +19,6 @@
#include "DNA_movieclip_types.h" /* MovieClipUser */
#include "DNA_node_types.h" /* for bNodeInstanceKey */
#include "DNA_outliner_types.h" /* for TreeStoreElem */
#include "DNA_sequence_types.h" /* SequencerScopes */
#include "DNA_vec_types.h"
/* Hum ... Not really nice... but needed for spacebuts. */
#include "DNA_view2d_types.h"
@ -67,9 +66,15 @@ namespace blender::ed::outliner {
struct SpaceOutliner_Runtime;
} // namespace blender::ed::outliner
using SpaceOutliner_Runtime = blender::ed::outliner::SpaceOutliner_Runtime;
namespace blender::ed::seq {
struct SpaceSeq_Runtime;
} // namespace blender::ed::seq
using SpaceSeq_Runtime = blender::ed::seq::SpaceSeq_Runtime;
#else
typedef struct SpaceNode_Runtime SpaceNode_Runtime;
typedef struct SpaceOutliner_Runtime SpaceOutliner_Runtime;
typedef struct SpaceSeq_Runtime SpaceSeq_Runtime;
#endif
aras_p marked this conversation as resolved Outdated

What about putting the runtime struct into the editor's namespace, like the node and outliner runtime structs?

What about putting the runtime struct into the editor's namespace, like the node and outliner runtime structs?
/** Defined in `file_intern.hh`. */
@ -631,15 +636,6 @@ typedef enum eSpaceSeq_SequencerTimelineOverlay_Flag {
SEQ_TIMELINE_SHOW_GRID = (1 << 18),
} eSpaceSeq_SequencerTimelineOverlay_Flag;
typedef struct SpaceSeqRuntime {
/** Required for Thumbnail job start condition. */
struct rctf last_thumbnail_area;
/** Stores lists of most recently displayed thumbnails. */
struct GHash *last_displayed_thumbnails;
int rename_channel_index;
float timeline_clamp_custom_range;
} SpaceSeqRuntime;
/** Sequencer. */
typedef struct SpaceSeq {
SpaceLink *next, *prev;
@ -678,8 +674,6 @@ typedef struct SpaceSeq {
/** Grease-pencil data. */
struct bGPdata *gpd;
/** Different scoped displayed in space. */
struct SequencerScopes scopes;
struct SequencerPreviewOverlay preview_overlay;
struct SequencerTimelineOverlay timeline_overlay;
@ -687,7 +681,7 @@ typedef struct SpaceSeq {
char multiview_eye;
char _pad2[7];
SpaceSeqRuntime runtime;
SpaceSeq_Runtime *runtime;
} SpaceSeq;
/** #SpaceSeq.mainb */

View File

@ -12,6 +12,7 @@
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"

View File

@ -13,6 +13,7 @@ struct Main;
struct Scene;
struct Sequence;
struct bSound;
struct SequenceModifierData;
struct SequencerSoundEqualizer;
struct SoundModifierWorkerInfo;
struct BlendWriter;

View File

@ -54,6 +54,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"