1101 lines
34 KiB
C++
1101 lines
34 KiB
C++
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup spseq
|
|
*/
|
|
|
|
#include <cmath>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
#include "DNA_gpencil_legacy_types.h"
|
|
#include "DNA_mask_types.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
#include "BLI_ghash.h"
|
|
#include "BLI_math_base.h"
|
|
|
|
#include "BKE_global.hh"
|
|
#include "BKE_lib_query.hh"
|
|
#include "BKE_lib_remap.hh"
|
|
#include "BKE_screen.hh"
|
|
#include "BKE_sequencer_offscreen.h"
|
|
|
|
#include "GPU_state.hh"
|
|
|
|
#include "ED_markers.hh"
|
|
#include "ED_screen.hh"
|
|
#include "ED_space_api.hh"
|
|
#include "ED_time_scrub_ui.hh"
|
|
#include "ED_transform.hh"
|
|
#include "ED_view3d.hh"
|
|
#include "ED_view3d_offscreen.hh" /* Only for sequencer view3d drawing callback. */
|
|
|
|
#include "WM_api.hh"
|
|
#include "WM_message.hh"
|
|
|
|
#include "SEQ_sequencer.hh"
|
|
#include "SEQ_time.hh"
|
|
#include "SEQ_transform.hh"
|
|
#include "SEQ_utils.hh"
|
|
|
|
#include "UI_interface.hh"
|
|
#include "UI_view2d.hh"
|
|
|
|
#include "BLO_read_write.hh"
|
|
|
|
/* Only for cursor drawing. */
|
|
#include "DRW_engine.hh"
|
|
|
|
/* Own include. */
|
|
#include "sequencer_intern.hh"
|
|
|
|
/**************************** common state *****************************/
|
|
|
|
static void sequencer_scopes_tag_refresh(ScrArea *area)
|
|
{
|
|
SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
|
|
sseq->runtime->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 ********************* */
|
|
|
|
static ARegion *sequencer_find_region(ScrArea *area, short type)
|
|
{
|
|
|
|
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
|
if (region->regiontype == type) {
|
|
return region;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/* ******************** default callbacks for sequencer space ***************** */
|
|
|
|
static SpaceLink *sequencer_create(const ScrArea * /*area*/, const Scene *scene)
|
|
{
|
|
ARegion *region;
|
|
SpaceSeq *sseq;
|
|
|
|
sseq = MEM_cnew<SpaceSeq>("initsequencer");
|
|
sseq->spacetype = SPACE_SEQ;
|
|
sseq->chanshown = 0;
|
|
sseq->view = SEQ_VIEW_SEQUENCE;
|
|
sseq->mainb = SEQ_DRAW_IMG_IMBUF;
|
|
sseq->flag = SEQ_USE_ALPHA | SEQ_SHOW_MARKERS | SEQ_ZOOM_TO_FIT | SEQ_SHOW_OVERLAY;
|
|
sseq->preview_overlay.flag = SEQ_PREVIEW_SHOW_GPENCIL | SEQ_PREVIEW_SHOW_OUTLINE_SELECTED;
|
|
sseq->timeline_overlay.flag = SEQ_TIMELINE_SHOW_STRIP_NAME | SEQ_TIMELINE_SHOW_STRIP_SOURCE |
|
|
SEQ_TIMELINE_SHOW_STRIP_DURATION | SEQ_TIMELINE_SHOW_GRID |
|
|
SEQ_TIMELINE_SHOW_FCURVES | SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG |
|
|
SEQ_TIMELINE_SHOW_STRIP_RETIMING | SEQ_TIMELINE_ALL_WAVEFORMS;
|
|
|
|
/* Header. */
|
|
region = MEM_cnew<ARegion>("header for sequencer");
|
|
|
|
BLI_addtail(&sseq->regionbase, static_cast<void *>(region));
|
|
region->regiontype = RGN_TYPE_HEADER;
|
|
region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
|
|
|
|
/* Tool header. */
|
|
region = MEM_cnew<ARegion>("tool header for sequencer");
|
|
|
|
BLI_addtail(&sseq->regionbase, static_cast<void *>(region));
|
|
region->regiontype = RGN_TYPE_TOOL_HEADER;
|
|
region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
|
|
region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
|
|
|
|
/* Buttons/list view. */
|
|
region = MEM_cnew<ARegion>("buttons for sequencer");
|
|
|
|
BLI_addtail(&sseq->regionbase, static_cast<void *>(region));
|
|
region->regiontype = RGN_TYPE_UI;
|
|
region->alignment = RGN_ALIGN_RIGHT;
|
|
region->flag = RGN_FLAG_HIDDEN;
|
|
|
|
/* Toolbar. */
|
|
region = MEM_cnew<ARegion>("tools for sequencer");
|
|
|
|
BLI_addtail(&sseq->regionbase, static_cast<void *>(region));
|
|
region->regiontype = RGN_TYPE_TOOLS;
|
|
region->alignment = RGN_ALIGN_LEFT;
|
|
region->flag = RGN_FLAG_HIDDEN;
|
|
|
|
/* Channels. */
|
|
region = MEM_cnew<ARegion>("channels for sequencer");
|
|
|
|
BLI_addtail(&sseq->regionbase, static_cast<void *>(region));
|
|
region->regiontype = RGN_TYPE_CHANNELS;
|
|
region->alignment = RGN_ALIGN_LEFT;
|
|
region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
|
|
|
|
/* Preview region. */
|
|
/* NOTE: if you change values here, also change them in sequencer_init_preview_region. */
|
|
region = MEM_cnew<ARegion>("preview region for sequencer");
|
|
BLI_addtail(&sseq->regionbase, static_cast<void *>(region));
|
|
region->regiontype = RGN_TYPE_PREVIEW;
|
|
region->alignment = RGN_ALIGN_TOP;
|
|
/* For now, aspect ratio should be maintained, and zoom is clamped within sane default limits. */
|
|
region->v2d.keepzoom = V2D_KEEPASPECT | V2D_KEEPZOOM | V2D_LIMITZOOM;
|
|
region->v2d.minzoom = 0.001f;
|
|
region->v2d.maxzoom = 1000.0f;
|
|
region->v2d.tot.xmin = -960.0f; /* 1920 width centered. */
|
|
region->v2d.tot.ymin = -540.0f; /* 1080 height centered. */
|
|
region->v2d.tot.xmax = 960.0f;
|
|
region->v2d.tot.ymax = 540.0f;
|
|
region->v2d.min[0] = 0.0f;
|
|
region->v2d.min[1] = 0.0f;
|
|
region->v2d.max[0] = 12000.0f;
|
|
region->v2d.max[1] = 12000.0f;
|
|
region->v2d.cur = region->v2d.tot;
|
|
region->v2d.align = V2D_ALIGN_FREE;
|
|
region->v2d.keeptot = V2D_KEEPTOT_FREE;
|
|
|
|
/* Main region. */
|
|
region = MEM_cnew<ARegion>("main region for sequencer");
|
|
|
|
BLI_addtail(&sseq->regionbase, static_cast<void *>(region));
|
|
region->regiontype = RGN_TYPE_WINDOW;
|
|
|
|
/* Seq space goes from (0,8) to (0, efra). */
|
|
region->v2d.tot.xmin = 0.0f;
|
|
region->v2d.tot.ymin = 0.0f;
|
|
region->v2d.tot.xmax = scene->r.efra;
|
|
region->v2d.tot.ymax = 8.5f;
|
|
|
|
region->v2d.cur = region->v2d.tot;
|
|
|
|
region->v2d.min[0] = 10.0f;
|
|
region->v2d.min[1] = 1.0f;
|
|
|
|
region->v2d.max[0] = MAXFRAMEF;
|
|
region->v2d.max[1] = MAXSEQ;
|
|
|
|
region->v2d.minzoom = 0.01f;
|
|
region->v2d.maxzoom = 100.0f;
|
|
|
|
region->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
|
|
region->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
|
|
region->v2d.keepzoom = 0;
|
|
region->v2d.keeptot = 0;
|
|
region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
|
|
region->v2d.align = V2D_ALIGN_NO_NEG_Y;
|
|
|
|
return (SpaceLink *)sseq;
|
|
}
|
|
|
|
/* Not spacelink itself. */
|
|
static void sequencer_free(SpaceLink *sl)
|
|
{
|
|
SpaceSeq *sseq = (SpaceSeq *)sl;
|
|
MEM_delete(sseq->runtime);
|
|
|
|
#if 0
|
|
if (sseq->gpd) {
|
|
BKE_gpencil_free_data(sseq->gpd);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Space-type init callback. */
|
|
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)
|
|
{
|
|
wmWindowManager *wm = CTX_wm_manager(C);
|
|
wmWindow *window = CTX_wm_window(C);
|
|
SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
|
|
ARegion *region_main = sequencer_find_region(area, RGN_TYPE_WINDOW);
|
|
ARegion *region_preview = sequencer_find_region(area, RGN_TYPE_PREVIEW);
|
|
bool view_changed = false;
|
|
|
|
switch (sseq->view) {
|
|
case SEQ_VIEW_PREVIEW:
|
|
/* Reset scrolling when preview region just appears. */
|
|
if (!(region_preview->v2d.flag & V2D_IS_INIT)) {
|
|
region_preview->v2d.cur = region_preview->v2d.tot;
|
|
/* Only redraw, don't re-init. */
|
|
ED_area_tag_redraw(area);
|
|
}
|
|
if (region_preview->alignment != RGN_ALIGN_NONE) {
|
|
region_preview->alignment = RGN_ALIGN_NONE;
|
|
view_changed = true;
|
|
}
|
|
break;
|
|
case SEQ_VIEW_SEQUENCE_PREVIEW: {
|
|
/* Get available height (without DPI correction). */
|
|
const float height = (area->winy - ED_area_headersize()) / UI_SCALE_FAC;
|
|
|
|
/* We reuse hidden region's size, allows to find same layout as before if we just switch
|
|
* between one 'full window' view and the combined one. This gets lost if we switch to both
|
|
* 'full window' views before, though... Better than nothing. */
|
|
if (!(region_preview->v2d.flag & V2D_IS_INIT)) {
|
|
region_preview->v2d.cur = region_preview->v2d.tot;
|
|
region_main->sizey = int(height - region_preview->sizey);
|
|
region_preview->sizey = int(height - region_main->sizey);
|
|
view_changed = true;
|
|
}
|
|
if (region_preview->alignment != RGN_ALIGN_TOP) {
|
|
region_preview->alignment = RGN_ALIGN_TOP;
|
|
view_changed = true;
|
|
}
|
|
/* Final check that both preview and main height are reasonable. */
|
|
if (region_preview->sizey < 10 || region_main->sizey < 10 ||
|
|
region_preview->sizey + region_main->sizey > height)
|
|
{
|
|
region_preview->sizey = roundf(height * 0.4f);
|
|
region_main->sizey = int(height - region_preview->sizey);
|
|
view_changed = true;
|
|
}
|
|
break;
|
|
}
|
|
case SEQ_VIEW_SEQUENCE:
|
|
break;
|
|
}
|
|
|
|
if (view_changed) {
|
|
ED_area_init(wm, window, area);
|
|
ED_area_tag_redraw(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);
|
|
|
|
return (SpaceLink *)sseqn;
|
|
}
|
|
|
|
static void sequencer_listener(const wmSpaceTypeListenerParams *params)
|
|
{
|
|
ScrArea *area = params->area;
|
|
const wmNotifier *wmn = params->notifier;
|
|
|
|
/* Context changes. */
|
|
switch (wmn->category) {
|
|
case NC_SCENE:
|
|
switch (wmn->data) {
|
|
case ND_FRAME:
|
|
case ND_SEQUENCER:
|
|
sequencer_scopes_tag_refresh(area);
|
|
break;
|
|
}
|
|
break;
|
|
case NC_WINDOW:
|
|
case NC_SPACE:
|
|
if (wmn->data == ND_SPACE_SEQUENCER) {
|
|
sequencer_scopes_tag_refresh(area);
|
|
}
|
|
break;
|
|
case NC_GPENCIL:
|
|
if (wmn->data & ND_GPENCIL_EDITMODE) {
|
|
ED_area_tag_redraw(area);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* DO NOT make this static, this hides the symbol and breaks API generation script. */
|
|
extern "C" const char *sequencer_context_dir[]; /* Quiet warning. */
|
|
const char *sequencer_context_dir[] = {"edit_mask", nullptr};
|
|
|
|
static int /*eContextResult*/ sequencer_context(const bContext *C,
|
|
const char *member,
|
|
bContextDataResult *result)
|
|
{
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
if (CTX_data_dir(member)) {
|
|
CTX_data_dir_set(result, sequencer_context_dir);
|
|
|
|
return CTX_RESULT_OK;
|
|
}
|
|
if (CTX_data_equals(member, "edit_mask")) {
|
|
Mask *mask = SEQ_active_mask_get(scene);
|
|
if (mask) {
|
|
CTX_data_id_pointer_set(result, &mask->id);
|
|
}
|
|
return CTX_RESULT_OK;
|
|
}
|
|
|
|
return CTX_RESULT_MEMBER_NOT_FOUND;
|
|
}
|
|
|
|
static void SEQUENCER_GGT_navigate(wmGizmoGroupType *gzgt)
|
|
{
|
|
VIEW2D_GGT_navigate_impl(gzgt, "SEQUENCER_GGT_navigate");
|
|
}
|
|
|
|
static void SEQUENCER_GGT_gizmo2d(wmGizmoGroupType *gzgt)
|
|
{
|
|
gzgt->name = "Sequencer Transform Gizmo";
|
|
gzgt->idname = "SEQUENCER_GGT_gizmo2d";
|
|
|
|
gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
|
|
WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
|
|
|
|
gzgt->gzmap_params.spaceid = SPACE_SEQ;
|
|
gzgt->gzmap_params.regionid = RGN_TYPE_PREVIEW;
|
|
|
|
ED_widgetgroup_gizmo2d_xform_callbacks_set(gzgt);
|
|
}
|
|
|
|
static void SEQUENCER_GGT_gizmo2d_translate(wmGizmoGroupType *gzgt)
|
|
{
|
|
gzgt->name = "Sequencer Translate Gizmo";
|
|
gzgt->idname = "SEQUENCER_GGT_gizmo2d_translate";
|
|
|
|
gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
|
|
WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
|
|
|
|
gzgt->gzmap_params.spaceid = SPACE_SEQ;
|
|
gzgt->gzmap_params.regionid = RGN_TYPE_PREVIEW;
|
|
|
|
ED_widgetgroup_gizmo2d_xform_no_cage_callbacks_set(gzgt);
|
|
}
|
|
|
|
static void SEQUENCER_GGT_gizmo2d_resize(wmGizmoGroupType *gzgt)
|
|
{
|
|
gzgt->name = "Sequencer Transform Gizmo Resize";
|
|
gzgt->idname = "SEQUENCER_GGT_gizmo2d_resize";
|
|
|
|
gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
|
|
WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
|
|
|
|
gzgt->gzmap_params.spaceid = SPACE_SEQ;
|
|
gzgt->gzmap_params.regionid = RGN_TYPE_PREVIEW;
|
|
|
|
ED_widgetgroup_gizmo2d_resize_callbacks_set(gzgt);
|
|
}
|
|
|
|
static void SEQUENCER_GGT_gizmo2d_rotate(wmGizmoGroupType *gzgt)
|
|
{
|
|
gzgt->name = "Sequencer Transform Gizmo Resize";
|
|
gzgt->idname = "SEQUENCER_GGT_gizmo2d_rotate";
|
|
|
|
gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
|
|
WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
|
|
|
|
gzgt->gzmap_params.spaceid = SPACE_SEQ;
|
|
gzgt->gzmap_params.regionid = RGN_TYPE_PREVIEW;
|
|
|
|
ED_widgetgroup_gizmo2d_rotate_callbacks_set(gzgt);
|
|
}
|
|
|
|
static void sequencer_gizmos()
|
|
{
|
|
WM_gizmogrouptype_append(SEQUENCER_GGT_gizmo2d);
|
|
WM_gizmogrouptype_append(SEQUENCER_GGT_gizmo2d_translate);
|
|
WM_gizmogrouptype_append(SEQUENCER_GGT_gizmo2d_resize);
|
|
WM_gizmogrouptype_append(SEQUENCER_GGT_gizmo2d_rotate);
|
|
|
|
const wmGizmoMapType_Params params_preview = {SPACE_SEQ, RGN_TYPE_PREVIEW};
|
|
wmGizmoMapType *gzmap_type_preview = WM_gizmomaptype_ensure(¶ms_preview);
|
|
WM_gizmogrouptype_append_and_link(gzmap_type_preview, SEQUENCER_GGT_navigate);
|
|
}
|
|
|
|
/* *********************** sequencer (main) region ************************ */
|
|
|
|
static bool sequencer_main_region_poll(const RegionPollParams *params)
|
|
{
|
|
const SpaceSeq *sseq = (SpaceSeq *)params->area->spacedata.first;
|
|
return ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW);
|
|
}
|
|
|
|
/* Add handlers, stuff you only do once or on area/region changes. */
|
|
static void sequencer_main_region_init(wmWindowManager *wm, ARegion *region)
|
|
{
|
|
wmKeyMap *keymap;
|
|
ListBase *lb;
|
|
|
|
UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
|
|
|
|
#if 0
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", SPACE_EMPTY, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
#endif
|
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
|
|
/* Own keymap. */
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
|
|
/* Add drop boxes. */
|
|
lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
|
|
WM_event_add_dropbox_handler(®ion->handlers, lb);
|
|
}
|
|
|
|
/* Strip editing timeline. */
|
|
static void sequencer_main_region_draw(const bContext *C, ARegion *region)
|
|
{
|
|
draw_timeline_seq(C, region);
|
|
}
|
|
|
|
/* Strip editing timeline. */
|
|
static void sequencer_main_region_draw_overlay(const bContext *C, ARegion *region)
|
|
{
|
|
draw_timeline_seq_display(C, region);
|
|
}
|
|
|
|
static void sequencer_main_clamp_view(const bContext *C, ARegion *region)
|
|
{
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
|
|
|
if ((sseq->flag & SEQ_CLAMP_VIEW) == 0) {
|
|
return;
|
|
}
|
|
|
|
View2D *v2d = ®ion->v2d;
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
/* Transformation uses edge panning to move view. Also if smooth view is running, don't apply
|
|
* clamping to prevent overriding this functionality. */
|
|
if (G.moving || v2d->smooth_timer != nullptr) {
|
|
return;
|
|
}
|
|
|
|
/* Initialize default view with 7 channels, that are visible even if empty. */
|
|
rctf strip_boundbox;
|
|
BLI_rctf_init(&strip_boundbox, 0.0f, 0.0f, 1.0f, 6.0f);
|
|
Editing *ed = SEQ_editing_get(scene);
|
|
if (ed != nullptr) {
|
|
SEQ_timeline_expand_boundbox(scene, ed->seqbasep, &strip_boundbox);
|
|
}
|
|
|
|
/* Clamp Y max. Scrubbing area height must be added, so strips aren't occluded. */
|
|
rcti scrub_rect;
|
|
ED_time_scrub_region_rect_get(region, &scrub_rect);
|
|
const float pixel_view_size_y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
|
|
const float scrub_bar_height = BLI_rcti_size_y(&scrub_rect) * pixel_view_size_y;
|
|
|
|
/* Channel n has range of <n, n+1>, +1 for empty channel. */
|
|
strip_boundbox.ymax += 2.0f + scrub_bar_height;
|
|
|
|
/* Clamp Y min. Scroller and marker area height must be added, so strips aren't occluded. */
|
|
float scroll_bar_height = v2d->hor.ymax * pixel_view_size_y;
|
|
|
|
ListBase *markers = ED_context_get_markers(C);
|
|
if (markers != nullptr && !BLI_listbase_is_empty(markers)) {
|
|
float markers_size = UI_MARKER_MARGIN_Y * pixel_view_size_y;
|
|
strip_boundbox.ymin -= markers_size;
|
|
}
|
|
else {
|
|
strip_boundbox.ymin -= scroll_bar_height;
|
|
}
|
|
|
|
/* 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);
|
|
|
|
rctf view_clamped = v2d->cur;
|
|
|
|
const float range_y = BLI_rctf_size_y(&view_clamped);
|
|
if (view_clamped.ymax > strip_boundbox.ymax) {
|
|
view_clamped.ymax = strip_boundbox.ymax;
|
|
view_clamped.ymin = max_ff(strip_boundbox.ymin, strip_boundbox.ymax - range_y);
|
|
}
|
|
if (view_clamped.ymin < strip_boundbox.ymin) {
|
|
view_clamped.ymin = strip_boundbox.ymin;
|
|
view_clamped.ymax = min_ff(strip_boundbox.ymax, strip_boundbox.ymin + range_y);
|
|
}
|
|
|
|
v2d->cur = view_clamped;
|
|
}
|
|
|
|
static void sequencer_main_region_clamp_custom_set(const bContext *C, ARegion *region)
|
|
{
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
|
View2D *v2d = ®ion->v2d;
|
|
|
|
if ((v2d->flag & V2D_IS_NAVIGATING) == 0) {
|
|
sseq->runtime->timeline_clamp_custom_range = v2d->cur.ymax;
|
|
}
|
|
}
|
|
|
|
static void sequencer_main_region_layout(const bContext *C, ARegion *region)
|
|
{
|
|
sequencer_main_region_clamp_custom_set(C, region);
|
|
sequencer_main_clamp_view(C, region);
|
|
}
|
|
|
|
static void sequencer_main_region_view2d_changed(const bContext *C, ARegion *region)
|
|
{
|
|
sequencer_main_region_clamp_custom_set(C, region);
|
|
sequencer_main_clamp_view(C, region);
|
|
}
|
|
|
|
static void sequencer_main_region_listener(const wmRegionListenerParams *params)
|
|
{
|
|
ARegion *region = params->region;
|
|
const wmNotifier *wmn = params->notifier;
|
|
|
|
/* Context changes. */
|
|
switch (wmn->category) {
|
|
case NC_SCENE:
|
|
switch (wmn->data) {
|
|
case ND_FRAME:
|
|
case ND_FRAME_RANGE:
|
|
case ND_MARKERS:
|
|
case ND_RENDER_OPTIONS: /* For FPS and FPS Base. */
|
|
case ND_SEQUENCER:
|
|
case ND_RENDER_RESULT:
|
|
ED_region_tag_redraw(region);
|
|
WM_gizmomap_tag_refresh(region->gizmo_map);
|
|
break;
|
|
}
|
|
break;
|
|
case NC_ANIMATION:
|
|
switch (wmn->data) {
|
|
case ND_KEYFRAME:
|
|
ED_region_tag_redraw(region);
|
|
break;
|
|
}
|
|
break;
|
|
case NC_SPACE:
|
|
if (wmn->data == ND_SPACE_SEQUENCER) {
|
|
ED_region_tag_redraw(region);
|
|
WM_gizmomap_tag_refresh(region->gizmo_map);
|
|
}
|
|
break;
|
|
case NC_ID:
|
|
if (wmn->action == NA_RENAME) {
|
|
ED_region_tag_redraw(region);
|
|
}
|
|
break;
|
|
case NC_SCREEN:
|
|
if (ELEM(wmn->data, ND_ANIMPLAY)) {
|
|
ED_region_tag_redraw(region);
|
|
WM_gizmomap_tag_refresh(region->gizmo_map);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void sequencer_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
|
|
{
|
|
wmMsgBus *mbus = params->message_bus;
|
|
Scene *scene = params->scene;
|
|
ARegion *region = params->region;
|
|
|
|
wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
|
|
msg_sub_value_region_tag_redraw.owner = region;
|
|
msg_sub_value_region_tag_redraw.user_data = region;
|
|
msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
|
|
|
|
/* Timeline depends on scene properties. */
|
|
{
|
|
bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
|
|
const PropertyRNA *props[] = {
|
|
use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
|
|
use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
|
|
&rna_Scene_use_preview_range,
|
|
&rna_Scene_frame_current,
|
|
};
|
|
|
|
PointerRNA idptr = RNA_id_pointer_create(&scene->id);
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(props); i++) {
|
|
WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
|
|
}
|
|
}
|
|
|
|
{
|
|
StructRNA *type_array[] = {
|
|
&RNA_SequenceEditor,
|
|
|
|
&RNA_Sequence,
|
|
/* Members of 'Sequence'. */
|
|
&RNA_SequenceCrop,
|
|
&RNA_SequenceTransform,
|
|
&RNA_SequenceModifier,
|
|
&RNA_SequenceColorBalanceData,
|
|
};
|
|
wmMsgParams_RNA msg_key_params = {{nullptr}};
|
|
for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
|
|
msg_key_params.ptr.type = type_array[i];
|
|
WM_msg_subscribe_rna_params(
|
|
mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* *********************** header region ************************ */
|
|
/* Add handlers, stuff you only do once or on area/region changes. */
|
|
static void sequencer_header_region_init(wmWindowManager * /*wm*/, ARegion *region)
|
|
{
|
|
ED_region_header_init(region);
|
|
}
|
|
|
|
static void sequencer_header_region_draw(const bContext *C, ARegion *region)
|
|
{
|
|
ED_region_header(C, region);
|
|
}
|
|
|
|
/* *********************** toolbar region ************************ */
|
|
/* Add handlers, stuff you only do once or on area/region changes. */
|
|
static void sequencer_tools_region_init(wmWindowManager *wm, ARegion *region)
|
|
{
|
|
wmKeyMap *keymap;
|
|
|
|
region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
|
|
ED_region_panels_init(wm, region);
|
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
}
|
|
|
|
static void sequencer_tools_region_draw(const bContext *C, ARegion *region)
|
|
{
|
|
ScrArea *area = CTX_wm_area(C);
|
|
wmOperatorCallContext op_context = WM_OP_INVOKE_REGION_WIN;
|
|
|
|
LISTBASE_FOREACH (ARegion *, ar, &area->regionbase) {
|
|
if (ar->regiontype == RGN_TYPE_PREVIEW && region->regiontype == RGN_TYPE_TOOLS) {
|
|
op_context = WM_OP_INVOKE_REGION_PREVIEW;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (region->regiontype == RGN_TYPE_CHANNELS) {
|
|
op_context = WM_OP_INVOKE_REGION_CHANNELS;
|
|
}
|
|
|
|
ED_region_panels_ex(C, region, op_context, nullptr);
|
|
}
|
|
/* *********************** preview region ************************ */
|
|
|
|
static bool sequencer_preview_region_poll(const RegionPollParams *params)
|
|
{
|
|
const SpaceSeq *sseq = (SpaceSeq *)params->area->spacedata.first;
|
|
return ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW);
|
|
}
|
|
|
|
static void sequencer_preview_region_init(wmWindowManager *wm, ARegion *region)
|
|
{
|
|
wmKeyMap *keymap;
|
|
|
|
UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
|
|
|
|
#if 0
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", SPACE_EMPTY, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
#endif
|
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
|
|
/* Own keymap. */
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerPreview", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
|
|
ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_PREVIEW);
|
|
WM_event_add_dropbox_handler(®ion->handlers, lb);
|
|
}
|
|
|
|
static void sequencer_preview_region_layout(const bContext *C, ARegion *region)
|
|
{
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
|
|
|
if (sseq->flag & SEQ_ZOOM_TO_FIT) {
|
|
View2D *v2d = ®ion->v2d;
|
|
v2d->cur = v2d->tot;
|
|
}
|
|
}
|
|
|
|
static void sequencer_preview_region_view2d_changed(const bContext *C, ARegion * /*region*/)
|
|
{
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
|
sseq->flag &= ~SEQ_ZOOM_TO_FIT;
|
|
}
|
|
|
|
static bool is_cursor_visible(const SpaceSeq *sseq)
|
|
{
|
|
if (G.moving & G_TRANSFORM_CURSOR) {
|
|
return true;
|
|
}
|
|
|
|
if ((sseq->flag & SEQ_SHOW_OVERLAY) &&
|
|
(sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_2D_CURSOR) != 0)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void sequencer_preview_region_draw(const bContext *C, ARegion *region)
|
|
{
|
|
ScrArea *area = CTX_wm_area(C);
|
|
SpaceSeq *sseq = static_cast<SpaceSeq *>(area->spacedata.first);
|
|
Scene *scene = CTX_data_scene(C);
|
|
wmWindowManager *wm = CTX_wm_manager(C);
|
|
const bool draw_overlay = sseq->flag & SEQ_SHOW_OVERLAY;
|
|
const bool draw_frame_overlay = (scene->ed &&
|
|
(scene->ed->overlay_frame_flag & SEQ_EDIT_OVERLAY_FRAME_SHOW) &&
|
|
draw_overlay);
|
|
const bool is_playing = ED_screen_animation_playing(wm);
|
|
|
|
if (!(draw_frame_overlay && (sseq->overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_REFERENCE))) {
|
|
sequencer_draw_preview(C, scene, region, sseq, scene->r.cfra, 0, false, false);
|
|
}
|
|
|
|
if (draw_frame_overlay && sseq->overlay_frame_type != SEQ_OVERLAY_FRAME_TYPE_CURRENT) {
|
|
int over_cfra;
|
|
|
|
if (scene->ed->overlay_frame_flag & SEQ_EDIT_OVERLAY_FRAME_ABS) {
|
|
over_cfra = scene->ed->overlay_frame_abs;
|
|
}
|
|
else {
|
|
over_cfra = scene->r.cfra + scene->ed->overlay_frame_ofs;
|
|
}
|
|
|
|
if ((over_cfra != scene->r.cfra) || (sseq->overlay_frame_type != SEQ_OVERLAY_FRAME_TYPE_RECT))
|
|
{
|
|
sequencer_draw_preview(
|
|
C, scene, region, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
|
|
}
|
|
}
|
|
|
|
/* No need to show the cursor for scopes. */
|
|
if ((is_playing == false) && (sseq->mainb == SEQ_DRAW_IMG_IMBUF) && is_cursor_visible(sseq)) {
|
|
GPU_color_mask(true, true, true, true);
|
|
GPU_depth_mask(false);
|
|
GPU_depth_test(GPU_DEPTH_NONE);
|
|
|
|
float cursor_pixel[2];
|
|
SEQ_image_preview_unit_to_px(scene, sseq->cursor, cursor_pixel);
|
|
|
|
DRW_draw_cursor_2d_ex(region, cursor_pixel);
|
|
}
|
|
|
|
if ((is_playing == false) && (sseq->gizmo_flag & SEQ_GIZMO_HIDE) == 0) {
|
|
WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
|
|
}
|
|
|
|
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
|
|
const rcti *rect = ED_region_visible_rect(region);
|
|
int xoffset = rect->xmin + U.widget_unit;
|
|
int yoffset = rect->ymax;
|
|
ED_scene_draw_fps(scene, xoffset, &yoffset);
|
|
}
|
|
}
|
|
|
|
static void sequencer_preview_region_listener(const wmRegionListenerParams *params)
|
|
{
|
|
ARegion *region = params->region;
|
|
const wmNotifier *wmn = params->notifier;
|
|
|
|
WM_gizmomap_tag_refresh(region->gizmo_map);
|
|
|
|
/* Context changes. */
|
|
switch (wmn->category) {
|
|
case NC_GPENCIL:
|
|
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
|
|
ED_region_tag_redraw(region);
|
|
}
|
|
break;
|
|
case NC_SCENE:
|
|
switch (wmn->data) {
|
|
case ND_FRAME:
|
|
case ND_MARKERS:
|
|
case ND_SEQUENCER:
|
|
case ND_RENDER_OPTIONS:
|
|
case ND_DRAW_RENDER_VIEWPORT:
|
|
ED_region_tag_redraw(region);
|
|
break;
|
|
}
|
|
break;
|
|
case NC_ANIMATION:
|
|
switch (wmn->data) {
|
|
case ND_KEYFRAME:
|
|
ED_region_tag_redraw(region);
|
|
break;
|
|
}
|
|
break;
|
|
case NC_SPACE:
|
|
if (wmn->data == ND_SPACE_SEQUENCER) {
|
|
ED_region_tag_redraw(region);
|
|
}
|
|
break;
|
|
case NC_ID:
|
|
switch (wmn->data) {
|
|
case NA_RENAME:
|
|
ED_region_tag_redraw(region);
|
|
break;
|
|
}
|
|
break;
|
|
case NC_MASK:
|
|
if (wmn->action == NA_EDITED) {
|
|
ED_region_tag_redraw(region);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* *********************** buttons region ************************ */
|
|
|
|
/* Add handlers, stuff you only do once or on area/region changes. */
|
|
static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *region)
|
|
{
|
|
wmKeyMap *keymap;
|
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
|
|
UI_panel_category_active_set_default(region, "Strip");
|
|
ED_region_panels_init(wm, region);
|
|
}
|
|
|
|
static void sequencer_buttons_region_draw(const bContext *C, ARegion *region)
|
|
{
|
|
ED_region_panels(C, region);
|
|
}
|
|
|
|
static void sequencer_buttons_region_listener(const wmRegionListenerParams *params)
|
|
{
|
|
ARegion *region = params->region;
|
|
const wmNotifier *wmn = params->notifier;
|
|
|
|
/* Context changes. */
|
|
switch (wmn->category) {
|
|
case NC_GPENCIL:
|
|
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
|
|
ED_region_tag_redraw(region);
|
|
}
|
|
break;
|
|
case NC_SCENE:
|
|
switch (wmn->data) {
|
|
case ND_FRAME:
|
|
case ND_SEQUENCER:
|
|
ED_region_tag_redraw(region);
|
|
break;
|
|
}
|
|
break;
|
|
case NC_SPACE:
|
|
if (wmn->data == ND_SPACE_SEQUENCER) {
|
|
ED_region_tag_redraw(region);
|
|
}
|
|
break;
|
|
case NC_ID:
|
|
if (wmn->action == NA_RENAME) {
|
|
ED_region_tag_redraw(region);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void sequencer_id_remap(ScrArea * /*area*/,
|
|
SpaceLink *slink,
|
|
const blender::bke::id::IDRemapper &mappings)
|
|
{
|
|
SpaceSeq *sseq = (SpaceSeq *)slink;
|
|
mappings.apply(reinterpret_cast<ID **>(&sseq->gpd), ID_REMAP_APPLY_DEFAULT);
|
|
}
|
|
|
|
static void sequencer_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
|
|
{
|
|
SpaceSeq *sseq = reinterpret_cast<SpaceSeq *>(space_link);
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sseq->gpd, IDWALK_CB_USER);
|
|
}
|
|
|
|
/* ************************************* */
|
|
|
|
static bool sequencer_channel_region_poll(const RegionPollParams *params)
|
|
{
|
|
const SpaceSeq *sseq = (SpaceSeq *)params->area->spacedata.first;
|
|
return ELEM(sseq->view, SEQ_VIEW_SEQUENCE);
|
|
}
|
|
|
|
/* add handlers, stuff you only do once or on area/region changes */
|
|
static void sequencer_channel_region_init(wmWindowManager *wm, ARegion *region)
|
|
{
|
|
wmKeyMap *keymap;
|
|
|
|
region->alignment = RGN_ALIGN_LEFT;
|
|
|
|
UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
|
|
|
|
keymap = WM_keymap_ensure(wm->defaultconf, "Sequencer Channels", SPACE_SEQ, RGN_TYPE_WINDOW);
|
|
WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
|
|
}
|
|
|
|
static void sequencer_channel_region_draw(const bContext *C, ARegion *region)
|
|
{
|
|
draw_channels(C, region);
|
|
}
|
|
|
|
static void sequencer_space_blend_read_data(BlendDataReader * /*reader*/, SpaceLink *sl)
|
|
{
|
|
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
|
|
*
|
|
* otherwise it'll lead to lost grease data on open because it'll likely be
|
|
* read from file after all other users of grease pencil and newdataadr would
|
|
* simple return nullptr here (sergey)
|
|
*/
|
|
#if 0
|
|
if (sseq->gpd) {
|
|
sseq->gpd = newdataadr(fd, sseq->gpd);
|
|
BKE_gpencil_blend_read_data(fd, sseq->gpd);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void sequencer_space_blend_write(BlendWriter *writer, SpaceLink *sl)
|
|
{
|
|
BLO_write_struct(writer, SpaceSeq, sl);
|
|
}
|
|
|
|
void ED_spacetype_sequencer()
|
|
{
|
|
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
|
|
ARegionType *art;
|
|
|
|
st->spaceid = SPACE_SEQ;
|
|
STRNCPY(st->name, "Sequencer");
|
|
|
|
st->create = sequencer_create;
|
|
st->free = sequencer_free;
|
|
st->init = sequencer_init;
|
|
st->duplicate = sequencer_duplicate;
|
|
st->operatortypes = sequencer_operatortypes;
|
|
st->keymap = sequencer_keymap;
|
|
st->context = sequencer_context;
|
|
st->gizmos = sequencer_gizmos;
|
|
st->dropboxes = sequencer_dropboxes;
|
|
st->refresh = sequencer_refresh;
|
|
st->listener = sequencer_listener;
|
|
st->id_remap = sequencer_id_remap;
|
|
st->foreach_id = sequencer_foreach_id;
|
|
st->blend_read_data = sequencer_space_blend_read_data;
|
|
st->blend_read_after_liblink = nullptr;
|
|
st->blend_write = sequencer_space_blend_write;
|
|
|
|
/* Create regions: */
|
|
/* Main window. */
|
|
art = MEM_cnew<ARegionType>("spacetype sequencer region");
|
|
art->regionid = RGN_TYPE_WINDOW;
|
|
art->poll = sequencer_main_region_poll;
|
|
art->init = sequencer_main_region_init;
|
|
art->draw = sequencer_main_region_draw;
|
|
art->draw_overlay = sequencer_main_region_draw_overlay;
|
|
art->layout = sequencer_main_region_layout;
|
|
art->on_view2d_changed = sequencer_main_region_view2d_changed;
|
|
art->listener = sequencer_main_region_listener;
|
|
art->message_subscribe = sequencer_main_region_message_subscribe;
|
|
art->keymapflag = ED_KEYMAP_TOOL | ED_KEYMAP_GIZMO | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES |
|
|
ED_KEYMAP_ANIMATION;
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
/* Preview. */
|
|
art = MEM_cnew<ARegionType>("spacetype sequencer region");
|
|
art->regionid = RGN_TYPE_PREVIEW;
|
|
art->poll = sequencer_preview_region_poll;
|
|
art->init = sequencer_preview_region_init;
|
|
art->layout = sequencer_preview_region_layout;
|
|
art->on_view2d_changed = sequencer_preview_region_view2d_changed;
|
|
art->draw = sequencer_preview_region_draw;
|
|
art->listener = sequencer_preview_region_listener;
|
|
art->keymapflag = ED_KEYMAP_TOOL | ED_KEYMAP_GIZMO | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES |
|
|
ED_KEYMAP_GPENCIL;
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
/* List-view/buttons. */
|
|
art = MEM_cnew<ARegionType>("spacetype sequencer region");
|
|
art->regionid = RGN_TYPE_UI;
|
|
art->prefsizex = UI_SIDEBAR_PANEL_WIDTH * 1.3f;
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
|
|
art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
|
|
art->listener = sequencer_buttons_region_listener;
|
|
art->init = sequencer_buttons_region_init;
|
|
art->draw = sequencer_buttons_region_draw;
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
sequencer_buttons_register(art);
|
|
/* Toolbar. */
|
|
art = MEM_cnew<ARegionType>("spacetype sequencer tools region");
|
|
art->regionid = RGN_TYPE_TOOLS;
|
|
art->prefsizex = int(UI_TOOLBAR_WIDTH);
|
|
art->prefsizey = 50; /* XXX */
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
|
|
art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
|
|
art->snap_size = ED_region_generic_tools_region_snap_size;
|
|
art->init = sequencer_tools_region_init;
|
|
art->draw = sequencer_tools_region_draw;
|
|
art->listener = sequencer_main_region_listener;
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
/* Channels. */
|
|
art = MEM_cnew<ARegionType>("spacetype sequencer channels");
|
|
art->regionid = RGN_TYPE_CHANNELS;
|
|
art->prefsizex = UI_COMPACT_PANEL_WIDTH;
|
|
art->keymapflag = ED_KEYMAP_UI;
|
|
art->poll = sequencer_channel_region_poll;
|
|
art->init = sequencer_channel_region_init;
|
|
art->draw = sequencer_channel_region_draw;
|
|
art->listener = sequencer_main_region_listener;
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
/* Tool header. */
|
|
art = MEM_cnew<ARegionType>("spacetype sequencer tool header region");
|
|
art->regionid = RGN_TYPE_TOOL_HEADER;
|
|
art->prefsizey = HEADERY;
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
|
|
art->listener = sequencer_main_region_listener;
|
|
art->init = sequencer_header_region_init;
|
|
art->draw = sequencer_header_region_draw;
|
|
art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
/* Header. */
|
|
art = MEM_cnew<ARegionType>("spacetype sequencer region");
|
|
art->regionid = RGN_TYPE_HEADER;
|
|
art->prefsizey = HEADERY;
|
|
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
|
|
|
|
art->init = sequencer_header_region_init;
|
|
art->draw = sequencer_header_region_draw;
|
|
art->listener = sequencer_main_region_listener;
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
/* HUD. */
|
|
art = ED_area_type_hud(st->spaceid);
|
|
BLI_addhead(&st->regiontypes, art);
|
|
|
|
BKE_spacetype_register(std::move(st));
|
|
|
|
/* Set the sequencer callback when not in background mode. */
|
|
if (G.background == 0) {
|
|
sequencer_view3d_fn = reinterpret_cast<SequencerDrawView>(
|
|
ED_view3d_draw_offscreen_imbuf_simple);
|
|
}
|
|
}
|