Sequencer: 2D cursor for the preview & transform
- Use 2D cursor in the preview space using shortcuts matching the UV editor and 3D view. - Add Cursor tool, cursor transform. - Support for cursor and bound-box pivot. - Add pivot pie menu.
This commit is contained in:
parent
919e513fa8
commit
d04d27b406
|
@ -2826,6 +2826,8 @@ def km_sequencerpreview(params):
|
|||
value=params.select_mouse_value_fallback,
|
||||
legacy=params.legacy,
|
||||
),
|
||||
op_menu_pie("SEQUENCER_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
|
||||
|
||||
("sequencer.view_all_preview", {"type": 'HOME', "value": 'PRESS'}, None),
|
||||
("sequencer.view_all_preview", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
|
||||
("sequencer.view_ghost_border", {"type": 'O', "value": 'PRESS'}, None),
|
||||
|
@ -2862,6 +2864,18 @@ def km_sequencerpreview(params):
|
|||
*_template_items_context_menu("SEQUENCER_MT_preview_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
# 2D cursor.
|
||||
if params.cursor_tweak_event:
|
||||
items.extend([
|
||||
("sequencer.cursor_set", params.cursor_set_event, None),
|
||||
("transform.translate", params.cursor_tweak_event,
|
||||
{"properties": [("release_confirm", True), ("cursor_transform", True)]}),
|
||||
])
|
||||
else:
|
||||
items.extend([
|
||||
("sequencer.cursor_set", params.cursor_set_event, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
|
@ -7465,13 +7479,13 @@ def km_sequencer_editor_tool_select(params, *, fallback):
|
|||
_fallback_id("Sequencer Tool: Tweak", fallback),
|
||||
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
# TODO: Use 2D cursor for preview region (currently `sequencer.sample`).
|
||||
*([] if fallback else
|
||||
_template_items_tool_select(params, "sequencer.select", "sequencer.sample", extend="toggle")
|
||||
_template_items_tool_select(params, "sequencer.select", "sequencer.cursor_set", extend="toggle")
|
||||
),
|
||||
*([] if (not params.use_fallback_tool_rmb) else _template_sequencer_generic_select(
|
||||
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
|
||||
|
||||
# Ignored for preview.
|
||||
*_template_items_change_frame(params),
|
||||
]},
|
||||
)
|
||||
|
@ -7490,6 +7504,7 @@ def km_sequencer_editor_tool_select_box(params, *, fallback):
|
|||
*_template_sequencer_select_for_fallback(params, fallback),
|
||||
|
||||
# RMB select can already set the frame, match the tweak tool.
|
||||
# Ignored for preview.
|
||||
*(_template_items_change_frame(params)
|
||||
if params.select_mouse == 'LEFTMOUSE' else []),
|
||||
]},
|
||||
|
@ -7506,6 +7521,19 @@ def km_sequencer_editor_tool_generic_sample(params):
|
|||
)
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_cursor(params):
|
||||
return (
|
||||
"Sequencer Tool: Cursor",
|
||||
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("sequencer.cursor_set", {"type": params.tool_mouse, "value": 'PRESS'}, None),
|
||||
# Don't use `tool_maybe_tweak_event` since it conflicts with `PRESS` that places the cursor.
|
||||
("transform.translate", params.tool_tweak_event,
|
||||
{"properties": [("release_confirm", True), ("cursor_transform", True)]}),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_blade(_params):
|
||||
return (
|
||||
"Sequencer Tool: Blade",
|
||||
|
@ -7808,6 +7836,7 @@ def generate_keymaps(params=None):
|
|||
*(km_sequencer_editor_tool_select_box(params, fallback=fallback) for fallback in (False, True)),
|
||||
km_sequencer_editor_tool_blade(params),
|
||||
km_sequencer_editor_tool_generic_sample(params),
|
||||
km_sequencer_editor_tool_cursor(params),
|
||||
km_sequencer_editor_tool_scale(params),
|
||||
km_sequencer_editor_tool_rotate(params),
|
||||
km_sequencer_editor_tool_move(params),
|
||||
|
|
|
@ -1042,6 +1042,22 @@ class SEQUENCER_MT_preview_context_menu(Menu):
|
|||
pass
|
||||
|
||||
|
||||
class SEQUENCER_MT_pivot_pie(Menu):
|
||||
bl_label = "Pivot Point"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
pie = layout.menu_pie()
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
sequencer_tool_settings = context.tool_settings.sequencer_tool_settings
|
||||
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CENTER')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CURSOR')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='INDIVIDUAL_ORIGINS')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='MEDIAN')
|
||||
|
||||
|
||||
class SequencerButtonsPanel:
|
||||
bl_space_type = 'SEQUENCE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
|
@ -2185,6 +2201,22 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
|
|||
col.prop(st, "show_separate_color")
|
||||
|
||||
|
||||
class SEQUENCER_PT_view_cursor(SequencerButtonsPanel_Output, Panel):
|
||||
bl_category = "View"
|
||||
bl_label = "2D Cursor"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
st = context.space_data
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
col = layout.column()
|
||||
col.prop(st, "cursor_location", text="Location")
|
||||
|
||||
|
||||
class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
|
||||
bl_label = "Frame Overlay"
|
||||
bl_category = "View"
|
||||
|
@ -2464,6 +2496,7 @@ classes = (
|
|||
SEQUENCER_MT_color_tag_picker,
|
||||
SEQUENCER_MT_context_menu,
|
||||
SEQUENCER_MT_preview_context_menu,
|
||||
SEQUENCER_MT_pivot_pie,
|
||||
|
||||
SEQUENCER_PT_color_tag_picker,
|
||||
|
||||
|
@ -2500,6 +2533,7 @@ classes = (
|
|||
SEQUENCER_PT_custom_props,
|
||||
|
||||
SEQUENCER_PT_view,
|
||||
SEQUENCER_PT_view_cursor,
|
||||
SEQUENCER_PT_frame_overlay,
|
||||
SEQUENCER_PT_view_safe_areas,
|
||||
SEQUENCER_PT_view_safe_areas_center_cut,
|
||||
|
|
|
@ -2440,6 +2440,19 @@ class _defs_node_edit:
|
|||
|
||||
class _defs_sequencer_generic:
|
||||
|
||||
@ToolDef.from_fn
|
||||
def cursor():
|
||||
return dict(
|
||||
idname="builtin.cursor",
|
||||
label="Cursor",
|
||||
description=(
|
||||
"Set the cursor location, drag to transform"
|
||||
),
|
||||
icon="ops.generic.cursor",
|
||||
keymap="Sequencer Tool: Cursor",
|
||||
options={'KEYMAP_FALLBACK'},
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def blade():
|
||||
def draw_settings(_context, layout, tool):
|
||||
|
@ -3094,6 +3107,8 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
],
|
||||
'PREVIEW': [
|
||||
*_tools_select,
|
||||
_defs_sequencer_generic.cursor,
|
||||
None,
|
||||
_defs_sequencer_generic.translate,
|
||||
_defs_sequencer_generic.rotate,
|
||||
_defs_sequencer_generic.scale,
|
||||
|
@ -3106,6 +3121,8 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
],
|
||||
'SEQUENCER_PREVIEW': [
|
||||
*_tools_select,
|
||||
_defs_sequencer_generic.cursor,
|
||||
None,
|
||||
_defs_sequencer_generic.translate,
|
||||
_defs_sequencer_generic.rotate,
|
||||
_defs_sequencer_generic.scale,
|
||||
|
|
|
@ -179,6 +179,9 @@ void DRW_viewport_data_free(struct DRWData *drw_data);
|
|||
bool DRW_opengl_context_release(void);
|
||||
void DRW_opengl_context_activate(bool drw_state);
|
||||
|
||||
/* We may want to move this into a more general location. */
|
||||
void DRW_draw_cursor_2d_ex(const struct ARegion *region, const float cursor[2]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_util.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "GPU_immediate.h"
|
||||
|
@ -226,6 +227,46 @@ static bool is_cursor_visible_2d(const DRWContextState *draw_ctx)
|
|||
return (sima->overlay.flag & SI_OVERLAY_SHOW_OVERLAYS) != 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generic Cursor
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \note This doesn't require the draw context to be in use.
|
||||
*/
|
||||
void DRW_draw_cursor_2d_ex(const ARegion *region, const float cursor[2])
|
||||
{
|
||||
int co[2];
|
||||
UI_view2d_view_to_region(®ion->v2d, cursor[0], cursor[1], &co[0], &co[1]);
|
||||
|
||||
/* Draw nice Anti Aliased cursor. */
|
||||
GPU_line_width(1.0f);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
GPU_line_smooth(true);
|
||||
|
||||
/* Draw lines */
|
||||
float original_proj[4][4];
|
||||
GPU_matrix_projection_get(original_proj);
|
||||
GPU_matrix_push();
|
||||
ED_region_pixelspace(region);
|
||||
GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f);
|
||||
GPU_matrix_scale_2f(U.widget_unit, U.widget_unit);
|
||||
|
||||
GPUBatch *cursor_batch = DRW_cache_cursor_get(true);
|
||||
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR);
|
||||
GPU_batch_set_shader(cursor_batch, shader);
|
||||
|
||||
GPU_batch_draw(cursor_batch);
|
||||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
GPU_line_smooth(false);
|
||||
GPU_matrix_pop();
|
||||
GPU_matrix_projection_set(original_proj);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
void DRW_draw_cursor_2d(void)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
|
@ -236,33 +277,8 @@ void DRW_draw_cursor_2d(void)
|
|||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
|
||||
if (is_cursor_visible_2d(draw_ctx)) {
|
||||
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
|
||||
int co[2];
|
||||
UI_view2d_view_to_region(®ion->v2d, sima->cursor[0], sima->cursor[1], &co[0], &co[1]);
|
||||
|
||||
/* Draw nice Anti Aliased cursor. */
|
||||
GPU_line_width(1.0f);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
GPU_line_smooth(true);
|
||||
|
||||
/* Draw lines */
|
||||
float original_proj[4][4];
|
||||
GPU_matrix_projection_get(original_proj);
|
||||
GPU_matrix_push();
|
||||
ED_region_pixelspace(region);
|
||||
GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f);
|
||||
GPU_matrix_scale_2f(U.widget_unit, U.widget_unit);
|
||||
|
||||
GPUBatch *cursor_batch = DRW_cache_cursor_get(true);
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR);
|
||||
GPU_batch_set_shader(cursor_batch, shader);
|
||||
|
||||
GPU_batch_draw(cursor_batch);
|
||||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
GPU_line_smooth(false);
|
||||
GPU_matrix_pop();
|
||||
GPU_matrix_projection_set(original_proj);
|
||||
const SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
|
||||
DRW_draw_cursor_2d_ex(region, sima->cursor);
|
||||
}
|
||||
}
|
||||
/** \} */
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
struct ARegion;
|
||||
|
||||
void DRW_draw_region_info(void);
|
||||
void DRW_clear_background(void);
|
||||
void DRW_draw_cursor(void);
|
||||
|
|
|
@ -74,9 +74,17 @@ static bool change_frame_poll(bContext *C)
|
|||
* this shouldn't show up in 3D editor (or others without 2D timeline view) via search
|
||||
*/
|
||||
if (area) {
|
||||
if (ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
|
||||
if (ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_CLIP)) {
|
||||
return true;
|
||||
}
|
||||
if (area->spacetype == SPACE_SEQ) {
|
||||
/* Check the region type so tools (which are shared between preview/strip view)
|
||||
* don't conflict with actions which can have the same key bound (2D cursor for example). */
|
||||
const ARegion *region = CTX_wm_region(C);
|
||||
if (region && region->regiontype == RGN_TYPE_WINDOW) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (area->spacetype == SPACE_GRAPH) {
|
||||
const SpaceGraph *sipo = area->spacedata.first;
|
||||
/* Driver Editor's X axis is not time. */
|
||||
|
|
|
@ -68,7 +68,7 @@ void ED_region_do_layout(struct bContext *C, struct ARegion *region);
|
|||
void ED_region_do_draw(struct bContext *C, struct ARegion *region);
|
||||
void ED_region_exit(struct bContext *C, struct ARegion *region);
|
||||
void ED_region_remove(struct bContext *C, struct ScrArea *area, struct ARegion *region);
|
||||
void ED_region_pixelspace(struct ARegion *region);
|
||||
void ED_region_pixelspace(const struct ARegion *region);
|
||||
void ED_region_update_rect(struct ARegion *region);
|
||||
void ED_region_floating_init(struct ARegion *region);
|
||||
void ED_region_tag_redraw(struct ARegion *region);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct GPUBatch;
|
||||
struct Main;
|
||||
struct bContext;
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ static void region_draw_emboss(const ARegion *region, const rcti *scirct, int si
|
|||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
void ED_region_pixelspace(ARegion *region)
|
||||
void ED_region_pixelspace(const ARegion *region)
|
||||
{
|
||||
wmOrtho2_region_pixelspace(region);
|
||||
GPU_matrix_identity_set();
|
||||
|
|
|
@ -22,6 +22,7 @@ set(INC
|
|||
../../blenlib
|
||||
../../blentranslation
|
||||
../../depsgraph
|
||||
../../draw
|
||||
../../gpu
|
||||
../../imbuf
|
||||
../../makesdna
|
||||
|
|
|
@ -3397,3 +3397,64 @@ void SEQUENCER_OT_strip_color_tag_set(struct wmOperatorType *ot)
|
|||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Set 2D Cursor Operator
|
||||
* \{ */
|
||||
|
||||
static int sequencer_set_2d_cursor_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
|
||||
float cursor_pixel[2];
|
||||
RNA_float_get_array(op->ptr, "location", cursor_pixel);
|
||||
|
||||
SEQ_image_preview_unit_from_px(scene, cursor_pixel, sseq->cursor);
|
||||
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int sequencer_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
float cursor_pixel[2];
|
||||
UI_view2d_region_to_view(
|
||||
®ion->v2d, event->mval[0], event->mval[1], &cursor_pixel[0], &cursor_pixel[1]);
|
||||
|
||||
RNA_float_set_array(op->ptr, "location", cursor_pixel);
|
||||
|
||||
return sequencer_set_2d_cursor_exec(C, op);
|
||||
}
|
||||
|
||||
void SEQUENCER_OT_cursor_set(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Set 2D Cursor";
|
||||
ot->description = "Set 2D cursor location";
|
||||
ot->idname = "SEQUENCER_OT_cursor_set";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = sequencer_set_2d_cursor_exec;
|
||||
ot->invoke = sequencer_set_2d_cursor_invoke;
|
||||
ot->poll = sequencer_view_preview_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_float_vector(ot->srna,
|
||||
"location",
|
||||
2,
|
||||
NULL,
|
||||
-FLT_MAX,
|
||||
FLT_MAX,
|
||||
"Location",
|
||||
"Cursor location in normalized preview coordinates",
|
||||
-10.0f,
|
||||
10.0f);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -165,6 +165,7 @@ void SEQUENCER_OT_strip_transform_clear(struct wmOperatorType *ot);
|
|||
void SEQUENCER_OT_strip_transform_fit(struct wmOperatorType *ot);
|
||||
|
||||
void SEQUENCER_OT_strip_color_tag_set(struct wmOperatorType *ot);
|
||||
void SEQUENCER_OT_cursor_set(struct wmOperatorType *ot);
|
||||
|
||||
/* sequencer_select.c */
|
||||
void SEQUENCER_OT_select_all(struct wmOperatorType *ot);
|
||||
|
|
|
@ -80,6 +80,7 @@ void sequencer_operatortypes(void)
|
|||
WM_operatortype_append(SEQUENCER_OT_strip_transform_fit);
|
||||
|
||||
WM_operatortype_append(SEQUENCER_OT_strip_color_tag_set);
|
||||
WM_operatortype_append(SEQUENCER_OT_cursor_set);
|
||||
|
||||
/* sequencer_select.c */
|
||||
WM_operatortype_append(SEQUENCER_OT_select_all);
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "BKE_screen.h"
|
||||
#include "BKE_sequencer_offscreen.h"
|
||||
|
||||
#include "GPU_state.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_transform.h"
|
||||
|
@ -53,6 +55,7 @@
|
|||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "SEQ_transform.h"
|
||||
#include "SEQ_utils.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
@ -61,6 +64,9 @@
|
|||
|
||||
#include "IMB_imbuf.h"
|
||||
|
||||
/* Only for cursor drawing. */
|
||||
#include "DRW_engine.h"
|
||||
|
||||
/* Own include. */
|
||||
#include "sequencer_intern.h"
|
||||
|
||||
|
@ -803,6 +809,17 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region)
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
|
||||
|
||||
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
|
||||
#include "SEQ_transform.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_message.h"
|
||||
#include "WM_types.h"
|
||||
|
@ -128,6 +130,11 @@ void setTransformViewAspect(TransInfo *t, float r_aspect[3])
|
|||
ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]);
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_SEQ) {
|
||||
if (t->options & CTX_CURSOR) {
|
||||
SEQ_image_preview_unit_to_px(t->scene, r_aspect, r_aspect);
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_CLIP) {
|
||||
SpaceClip *sclip = t->area->spacedata.first;
|
||||
|
||||
|
|
|
@ -222,6 +222,7 @@ typedef enum {
|
|||
TC_POSE,
|
||||
TC_ARMATURE_VERTS,
|
||||
TC_CURSOR_IMAGE,
|
||||
TC_CURSOR_SEQUENCER,
|
||||
TC_CURSOR_VIEW3D,
|
||||
TC_CURVE_VERTS,
|
||||
TC_GRAPH_EDIT_DATA,
|
||||
|
|
|
@ -945,6 +945,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
|
|||
break;
|
||||
case TC_ARMATURE_VERTS:
|
||||
case TC_CURSOR_IMAGE:
|
||||
case TC_CURSOR_SEQUENCER:
|
||||
case TC_CURSOR_VIEW3D:
|
||||
case TC_CURVE_VERTS:
|
||||
case TC_GPENCIL:
|
||||
|
@ -1037,6 +1038,7 @@ static void init_proportional_edit(TransInfo *t)
|
|||
case TC_POSE: /* Disable PET, its not usable in pose mode yet T32444. */
|
||||
case TC_ARMATURE_VERTS:
|
||||
case TC_CURSOR_IMAGE:
|
||||
case TC_CURSOR_SEQUENCER:
|
||||
case TC_CURSOR_VIEW3D:
|
||||
case TC_NLA_DATA:
|
||||
case TC_OBJECT_TEXSPACE:
|
||||
|
@ -1112,6 +1114,7 @@ static void init_TransDataContainers(TransInfo *t,
|
|||
case TC_ACTION_DATA:
|
||||
case TC_GRAPH_EDIT_DATA:
|
||||
case TC_CURSOR_IMAGE:
|
||||
case TC_CURSOR_SEQUENCER:
|
||||
case TC_CURSOR_VIEW3D:
|
||||
case TC_MASKING_DATA:
|
||||
case TC_NLA_DATA:
|
||||
|
@ -1223,6 +1226,7 @@ static eTFlag flags_from_data_type(eTConvertType data_type)
|
|||
case TC_MESH_UV:
|
||||
return T_EDIT | T_POINTS | T_2D_EDIT;
|
||||
case TC_CURSOR_IMAGE:
|
||||
case TC_CURSOR_SEQUENCER:
|
||||
return T_2D_EDIT;
|
||||
case TC_PARTICLE_VERTS:
|
||||
return T_POINTS;
|
||||
|
@ -1249,6 +1253,9 @@ static eTConvertType convert_type_get(const TransInfo *t, Object **r_obj_armatur
|
|||
if (t->spacetype == SPACE_IMAGE) {
|
||||
convert_type = TC_CURSOR_IMAGE;
|
||||
}
|
||||
else if (t->spacetype == SPACE_SEQ) {
|
||||
convert_type = TC_CURSOR_SEQUENCER;
|
||||
}
|
||||
else {
|
||||
convert_type = TC_CURSOR_VIEW3D;
|
||||
}
|
||||
|
@ -1396,6 +1403,9 @@ void createTransData(bContext *C, TransInfo *t)
|
|||
case TC_CURSOR_IMAGE:
|
||||
createTransCursor_image(t);
|
||||
break;
|
||||
case TC_CURSOR_SEQUENCER:
|
||||
createTransCursor_sequencer(t);
|
||||
break;
|
||||
case TC_CURSOR_VIEW3D:
|
||||
createTransCursor_view3d(t);
|
||||
break;
|
||||
|
@ -1714,8 +1724,11 @@ void recalcData(TransInfo *t)
|
|||
case TC_CURSOR_IMAGE:
|
||||
recalcData_cursor_image(t);
|
||||
break;
|
||||
case TC_CURSOR_SEQUENCER:
|
||||
recalcData_cursor_sequencer(t);
|
||||
break;
|
||||
case TC_CURSOR_VIEW3D:
|
||||
recalcData_cursor(t);
|
||||
recalcData_cursor_view3d(t);
|
||||
break;
|
||||
case TC_GRAPH_EDIT_DATA:
|
||||
recalcData_graphedit(t);
|
||||
|
|
|
@ -85,9 +85,11 @@ void special_aftertrans_update__pose(bContext *C, TransInfo *t);
|
|||
|
||||
/* transform_convert_cursor.c */
|
||||
void createTransCursor_image(TransInfo *t);
|
||||
void createTransCursor_sequencer(TransInfo *t);
|
||||
void createTransCursor_view3d(TransInfo *t);
|
||||
void recalcData_cursor_image(TransInfo *t);
|
||||
void recalcData_cursor(TransInfo *t);
|
||||
void recalcData_cursor_sequencer(TransInfo *t);
|
||||
void recalcData_cursor_view3d(TransInfo *t);
|
||||
|
||||
/* transform_convert_curve.c */
|
||||
void createTransCurveVerts(TransInfo *t);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
/** \file
|
||||
* \ingroup edtransform
|
||||
*
|
||||
* Instead of transforming the selection, move the 2D/3D cursor.
|
||||
*/
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
@ -35,18 +37,12 @@
|
|||
#include "transform_convert.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Cursor Transform Creation
|
||||
*
|
||||
* Instead of transforming the selection, move the 2D/3D cursor.
|
||||
*
|
||||
/** \name Shared 2D Cursor Utilities
|
||||
* \{ */
|
||||
|
||||
void createTransCursor_image(TransInfo *t)
|
||||
static void createTransCursor_2D_impl(TransInfo *t, float cursor_location[2])
|
||||
{
|
||||
TransData *td;
|
||||
SpaceImage *sima = t->area->spacedata.first;
|
||||
float *cursor_location = sima->cursor;
|
||||
|
||||
{
|
||||
BLI_assert(t->data_container_len == 1);
|
||||
TransDataContainer *tc = t->data_container;
|
||||
|
@ -57,7 +53,7 @@ void createTransCursor_image(TransInfo *t)
|
|||
|
||||
td->flag = TD_SELECTED;
|
||||
|
||||
/* UV coords are scaled by aspects (see UVsToTransData). This also applies for the Cursor in the
|
||||
/* UV coords are scaled by aspects (see #UVsToTransData). This also applies for the Cursor in the
|
||||
* UV Editor which also means that for display and when the cursor coords are flushed
|
||||
* (recalcData_cursor_image), these are converted each time. */
|
||||
cursor_location[0] = cursor_location[0] * t->aspect[0];
|
||||
|
@ -74,6 +70,62 @@ void createTransCursor_image(TransInfo *t)
|
|||
copy_v3_v3(td->iloc, cursor_location);
|
||||
}
|
||||
|
||||
static void recalcData_cursor_2D_impl(TransInfo *t)
|
||||
{
|
||||
TransDataContainer *tc = t->data_container;
|
||||
TransData *td = tc->data;
|
||||
float aspect_inv[2];
|
||||
|
||||
aspect_inv[0] = 1.0f / t->aspect[0];
|
||||
aspect_inv[1] = 1.0f / t->aspect[1];
|
||||
|
||||
td->loc[0] = td->loc[0] * aspect_inv[0];
|
||||
td->loc[1] = td->loc[1] * aspect_inv[1];
|
||||
|
||||
DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Image Cursor
|
||||
* \{ */
|
||||
|
||||
void createTransCursor_image(TransInfo *t)
|
||||
{
|
||||
SpaceImage *sima = t->area->spacedata.first;
|
||||
createTransCursor_2D_impl(t, sima->cursor);
|
||||
}
|
||||
|
||||
void recalcData_cursor_image(TransInfo *t)
|
||||
{
|
||||
recalcData_cursor_2D_impl(t);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Sequencer Cursor
|
||||
* \{ */
|
||||
|
||||
void createTransCursor_sequencer(TransInfo *t)
|
||||
{
|
||||
SpaceSeq *sseq = t->area->spacedata.first;
|
||||
|
||||
createTransCursor_2D_impl(t, sseq->cursor);
|
||||
}
|
||||
|
||||
void recalcData_cursor_sequencer(TransInfo *t)
|
||||
{
|
||||
recalcData_cursor_2D_impl(t);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name View 3D Cursor
|
||||
* \{ */
|
||||
|
||||
void createTransCursor_view3d(TransInfo *t)
|
||||
{
|
||||
TransData *td;
|
||||
|
@ -133,28 +185,7 @@ void createTransCursor_view3d(TransInfo *t)
|
|||
td->ext->rotOrder = cursor->rotation_mode;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Recalc Cursor
|
||||
* \{ */
|
||||
|
||||
void recalcData_cursor_image(TransInfo *t)
|
||||
{
|
||||
TransDataContainer *tc = t->data_container;
|
||||
TransData *td = tc->data;
|
||||
float aspect_inv[2];
|
||||
|
||||
aspect_inv[0] = 1.0f / t->aspect[0];
|
||||
aspect_inv[1] = 1.0f / t->aspect[1];
|
||||
|
||||
td->loc[0] = td->loc[0] * aspect_inv[0];
|
||||
td->loc[1] = td->loc[1] * aspect_inv[1];
|
||||
|
||||
DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
|
||||
}
|
||||
|
||||
void recalcData_cursor(TransInfo *t)
|
||||
void recalcData_cursor_view3d(TransInfo *t)
|
||||
{
|
||||
DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "BKE_modifier.h"
|
||||
#include "BKE_paint.h"
|
||||
|
||||
#include "SEQ_transform.h"
|
||||
|
||||
#include "ED_clip.h"
|
||||
#include "ED_image.h"
|
||||
#include "ED_object.h"
|
||||
|
@ -885,12 +887,18 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
|
|||
|
||||
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
|
||||
{
|
||||
float cursor_local_buf[2];
|
||||
const float *cursor = NULL;
|
||||
|
||||
if (t->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = (SpaceImage *)t->area->spacedata.first;
|
||||
cursor = sima->cursor;
|
||||
}
|
||||
if (t->spacetype == SPACE_SEQ) {
|
||||
SpaceSeq *sseq = (SpaceSeq *)t->area->spacedata.first;
|
||||
SEQ_image_preview_unit_to_px(t->scene, sseq->cursor, cursor_local_buf);
|
||||
cursor = cursor_local_buf;
|
||||
}
|
||||
else if (t->spacetype == SPACE_CLIP) {
|
||||
SpaceClip *space_clip = (SpaceClip *)t->area->spacedata.first;
|
||||
cursor = space_clip->cursor;
|
||||
|
@ -1069,7 +1077,7 @@ static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[
|
|||
calculateCenterMedian(t, r_center);
|
||||
break;
|
||||
case V3D_AROUND_CURSOR:
|
||||
if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
|
||||
if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_SEQ, SPACE_CLIP)) {
|
||||
calculateCenterCursor2D(t, r_center);
|
||||
}
|
||||
else if (t->spacetype == SPACE_GRAPH) {
|
||||
|
|
|
@ -284,23 +284,25 @@ static bool gizmo2d_calc_center(const bContext *C, float r_center[2])
|
|||
ED_uvedit_center_from_pivot_ex(sima, scene, view_layer, r_center, sima->around, &has_select);
|
||||
}
|
||||
else if (area->spacetype == SPACE_SEQ) {
|
||||
SpaceSeq *sseq = area->spacedata.first;
|
||||
const int pivot_point = scene->toolsettings->sequencer_tool_settings->pivot_point;
|
||||
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
|
||||
SeqCollection *strips = SEQ_query_rendered_strips(seqbase, scene->r.cfra, 0);
|
||||
SEQ_filter_selected_strips(strips);
|
||||
has_select = SEQ_collection_len(strips) != 0;
|
||||
|
||||
if (SEQ_collection_len(strips) <= 0) {
|
||||
SEQ_collection_free(strips);
|
||||
return false;
|
||||
if (pivot_point == V3D_AROUND_CURSOR) {
|
||||
SEQ_image_preview_unit_to_px(scene, sseq->cursor, r_center);
|
||||
}
|
||||
|
||||
has_select = true;
|
||||
Sequence *seq;
|
||||
SEQ_ITERATOR_FOREACH (seq, strips) {
|
||||
float origin[2];
|
||||
SEQ_image_transform_origin_offset_pixelspace_get(scene, seq, origin);
|
||||
add_v2_v2(r_center, origin);
|
||||
else if (has_select) {
|
||||
Sequence *seq;
|
||||
SEQ_ITERATOR_FOREACH (seq, strips) {
|
||||
float origin[2];
|
||||
SEQ_image_transform_origin_offset_pixelspace_get(scene, seq, origin);
|
||||
add_v2_v2(r_center, origin);
|
||||
}
|
||||
mul_v2_fl(r_center, 1.0f / SEQ_collection_len(strips));
|
||||
}
|
||||
mul_v2_fl(r_center, 1.0f / SEQ_collection_len(strips));
|
||||
|
||||
SEQ_collection_free(strips);
|
||||
}
|
||||
|
|
|
@ -647,6 +647,9 @@ typedef struct SpaceSeq {
|
|||
int draw_flag;
|
||||
char _pad[4];
|
||||
|
||||
/** 2D cursor for transform. */
|
||||
float cursor[2];
|
||||
|
||||
/** Grease-pencil data. */
|
||||
struct bGPdata *gpd;
|
||||
|
||||
|
|
|
@ -3539,7 +3539,9 @@ static void rna_def_sequencer_tool_settings(BlenderRNA *brna)
|
|||
};
|
||||
|
||||
static const EnumPropertyItem pivot_points[] = {
|
||||
{V3D_AROUND_CENTER_BOUNDS, "CENTER", ICON_PIVOT_BOUNDBOX, "Bounding Box Center", ""},
|
||||
{V3D_AROUND_CENTER_MEDIAN, "MEDIAN", ICON_PIVOT_MEDIAN, "Median Point", ""},
|
||||
{V3D_AROUND_CURSOR, "CURSOR", ICON_PIVOT_CURSOR, "2D Cursor", "Pivot around the 2D cursor"},
|
||||
{V3D_AROUND_LOCAL_ORIGINS,
|
||||
"INDIVIDUAL_ORIGINS",
|
||||
ICON_PIVOT_INDIVIDUAL,
|
||||
|
|
|
@ -5690,6 +5690,13 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
|
|||
|
||||
rna_def_space_sequencer_preview_overlay(brna);
|
||||
rna_def_space_sequencer_timeline_overlay(brna);
|
||||
|
||||
/* transform */
|
||||
prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ);
|
||||
RNA_def_property_float_sdna(prop, NULL, "cursor");
|
||||
RNA_def_property_array(prop, 2);
|
||||
RNA_def_property_ui_text(prop, "2D Cursor Location", "2D cursor location for this view");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_space_text(BlenderRNA *brna)
|
||||
|
|
|
@ -70,6 +70,13 @@ void SEQ_image_transform_final_quad_get(const struct Scene *scene,
|
|||
const struct Sequence *seq,
|
||||
float r_quad[4][2]);
|
||||
|
||||
void SEQ_image_preview_unit_to_px(const struct Scene *scene,
|
||||
const float co_src[2],
|
||||
float co_dst[2]);
|
||||
void SEQ_image_preview_unit_from_px(const struct Scene *scene,
|
||||
const float co_src[2],
|
||||
float co_dst[2]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -520,3 +520,15 @@ void SEQ_image_transform_final_quad_get(const Scene *scene,
|
|||
mul_v2_v2(r_quad[2], mirror);
|
||||
mul_v2_v2(r_quad[3], mirror);
|
||||
}
|
||||
|
||||
void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2])
|
||||
{
|
||||
co_dst[0] = co_src[0] * scene->r.xsch;
|
||||
co_dst[1] = co_src[1] * scene->r.ysch;
|
||||
}
|
||||
|
||||
void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], float co_dst[2])
|
||||
{
|
||||
co_dst[0] = co_src[0] / scene->r.xsch;
|
||||
co_dst[1] = co_src[1] / scene->r.ysch;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue