52 if (
data ==
nullptr ||
data->runtime ==
nullptr) {
81 cursor_offset = std::clamp(cursor_offset, 0,
text->character_count);
83 int2 cursor_position{0, 0};
86 cursor_position.x = cursor_offset;
90 cursor_position.y += 1;
93 cursor_position.y = std::clamp(cursor_position.y, 0,
int(
text->lines.size() - 1));
94 cursor_position.x = std::clamp(
95 cursor_position.x, 0,
int(
text->lines[cursor_position.y].characters.size() - 1));
97 return cursor_position;
101 const int2 cursor_pos)
103 return text->lines[cursor_pos.y].characters[cursor_pos.x];
107 const int cursor_offset)
120 data->selection_start_offset = 0;
121 data->selection_end_offset = 0;
127 int sel_start_offset =
data->selection_start_offset;
128 int sel_end_offset =
data->selection_end_offset;
129 if (sel_start_offset > sel_end_offset) {
130 std::swap(sel_start_offset, sel_end_offset);
133 return IndexRange(sel_start_offset, sel_end_offset - sel_start_offset);
153 char *addr_start =
const_cast<char *
>(char_start.
str_ptr);
156 std::memmove(addr_start, addr_end,
BLI_strnlen(addr_end,
sizeof(
data->text)) + 1);
184 {
LINE_BEGIN,
"LINE_BEGIN", 0,
"Line Begin",
""},
185 {
LINE_END,
"LINE_END", 0,
"Line End",
""},
186 {
TEXT_BEGIN,
"TEXT_BEGIN", 0,
"Text Begin",
""},
187 {
TEXT_END,
"TEXT_END", 0,
"Text End",
""},
188 {
PREV_CHAR,
"PREVIOUS_CHARACTER", 0,
"Previous Character",
""},
189 {
NEXT_CHAR,
"NEXT_CHARACTER", 0,
"Next Character",
""},
190 {
PREV_WORD,
"PREVIOUS_WORD", 0,
"Previous Word",
""},
191 {
NEXT_WORD,
"NEXT_WORD", 0,
"Next Word",
""},
192 {
PREV_LINE,
"PREVIOUS_LINE", 0,
"Previous Line",
""},
193 {
NEXT_LINE,
"NEXT_LINE", 0,
"Next Line",
""},
194 {0,
nullptr, 0,
nullptr,
nullptr},
201 if (cursor_position.x + offset > cur_line.
characters.size() - 1 &&
202 cursor_position.y <
text->lines.size() - 1)
204 cursor_position.x = 0;
208 else if (cursor_position.x + offset < 0 && cursor_position.y > 0) {
210 cursor_position.x =
text->lines[cursor_position.y].characters.size() - 1;
213 cursor_position.x += offset;
214 const int position_max =
text->lines[cursor_position.y].characters.size() - 1;
215 cursor_position.x = std::clamp(cursor_position.x, 0, position_max);
217 return cursor_position;
223 const int cur_pos_x = cur_line.
characters[cursor_position.x].position.x;
225 const int line_max =
text->lines.size() - 1;
226 const int new_line_index = std::clamp(cursor_position.y + offset, 0, line_max);
229 if (cursor_position.y == new_line_index) {
230 return cursor_position;
234 int best_distance = std::numeric_limits<int>::max();
235 int best_character_index = 0;
242 best_character_index =
i;
246 cursor_position.x = best_character_index;
247 cursor_position.y = new_line_index;
248 return cursor_position;
254 cursor_position.x = cur_line.
characters.size() - 1;
255 return cursor_position;
260 return ELEM(chr1,
' ',
'\t',
'\n') && !
ELEM(chr2,
' ',
'\t',
'\n');
267 while (cursor_position.x > 0 || cursor_position.y > 0) {
275 cursor_position = prev_cursor_pos;
277 return cursor_position;
282 const int maxline =
text->lines.size() - 1;
283 const int maxchar =
text->lines.last().characters.size() - 1;
285 while ((cursor_position.x < maxchar) || (cursor_position.y < maxline)) {
294 return cursor_position;
304 data->selection_start_offset =
data->cursor_offset;
323 cursor_position.x = 0;
329 cursor_position = {0, 0};
332 cursor_position.y =
text->lines.size() - 1;
345 data->selection_end_offset =
data->cursor_offset;
349 data->cursor_offset ==
data->selection_start_offset)
361 ot->name =
"Move Cursor";
362 ot->description =
"Move cursor in text";
363 ot->idname =
"SEQUENCER_OT_text_cursor_move";
378 "Where to move cursor to, to make a selection");
381 ot->srna,
"select_text",
false,
"Select Text",
"Select text while moving cursor");
395 if (text_str_len + buf_len + 1 >
sizeof(
data->text)) {
396 return selection_was_deleted;
400 char *cursor_addr =
const_cast<char *
>(cur_char.
str_ptr);
401 const size_t move_str_len =
BLI_strnlen(cursor_addr,
sizeof(
data->text)) + 1;
403 std::memmove(cursor_addr + buf_len, cursor_addr, move_str_len);
404 std::memcpy(cursor_addr, buf, buf_len);
406 data->cursor_offset += 1;
419 if (in_buf_len == 0) {
444 ot->name =
"Insert Character";
445 ot->description =
"Insert text at cursor position";
446 ot->idname =
"SEQUENCER_OT_text_insert";
458 ot->srna,
"string",
nullptr, 512,
"String",
"String to be inserted at cursor position");
463 {
DEL_NEXT_SEL,
"NEXT_OR_SELECTION", 0,
"Next or Selection",
""},
464 {
DEL_PREV_SEL,
"PREVIOUS_OR_SELECTION", 0,
"Previous or Selection",
""},
465 {0,
nullptr, 0,
nullptr,
nullptr},
470 char *cursor_addr =
const_cast<char *
>(character.
str_ptr);
471 char *next_char_addr = cursor_addr + character.
byte_length;
472 std::memmove(cursor_addr, next_char_addr,
BLI_strnlen(next_char_addr,
sizeof(
data->text)) + 1);
489 if (
data->cursor_offset >=
text->character_count) {
496 if (
data->cursor_offset == 0) {
501 data->cursor_offset -= 1;
511 ot->name =
"Delete Character";
512 ot->description =
"Delete text at cursor position";
513 ot->idname =
"SEQUENCER_OT_text_delete";
528 "Which part of the text to delete");
547 ot->name =
"Insert Line Break";
548 ot->description =
"Insert line break at cursor position";
549 ot->idname =
"SEQUENCER_OT_text_line_break";
563 data->selection_start_offset = 0;
564 data->selection_end_offset =
data->runtime->character_count;
572 ot->name =
"Select All";
573 ot->description =
"Select all characters";
574 ot->idname =
"SEQUENCER_OT_text_select_all";
604 ot->name =
"Deselect All";
605 ot->description =
"Deselect all characters";
606 ot->idname =
"SEQUENCER_OT_text_deselect_all";
633 ot->name =
"Edit Text";
634 ot->description =
"Toggle text editing";
635 ot->idname =
"SEQUENCER_OT_text_edit_mode_toggle";
648 int best_cursor_offset = 0;
649 float best_distance = std::numeric_limits<float>::max();
656 best_cursor_offset = character.
index;
661 return best_cursor_offset;
678 const float view_aspect = scene->
r.
xasp / scene->
r.
yasp;
683 mouse_loc.x /= view_aspect;
685 mouse_loc -= view_offs;
696 bool make_selection =
false;
698 switch (event->
type) {
702 if (make_selection) {
703 data->selection_end_offset =
data->cursor_offset;
712 make_selection =
true;
714 data->selection_start_offset =
data->cursor_offset;
717 data->selection_end_offset =
data->cursor_offset;
758 ot->name =
"Set Cursor";
759 ot->description =
"Set cursor position in text";
760 ot->idname =
"SEQUENCER_OT_text_cursor_set";
773 ot->srna,
"select_text",
false,
"Select Text",
"Select text while moving cursor");
785 char clipboard_buf[
sizeof(
data->text)] = {0};
807 ot->name =
"Copy Text";
808 ot->description =
"Copy text to clipboard";
809 ot->idname =
"SEQUENCER_OT_text_edit_copy";
828 if (clipboard_len == 0) {
833 const int max_str_len =
sizeof(
data->text) - (
STRNLEN(
data->text) + 1);
836 const int fillable_len = std::min(clipboard_len, max_str_len);
840 size_t valid_str_len;
844 char *cursor_addr =
const_cast<char *
>(cur_char.
str_ptr);
845 const size_t move_str_len =
BLI_strnlen(cursor_addr,
sizeof(
data->text)) + 1;
847 std::memmove(cursor_addr + valid_str_len, cursor_addr, move_str_len);
848 std::memcpy(cursor_addr, clipboard_buf, valid_str_len);
850 data->cursor_offset += extra_offset;
860 ot->name =
"Paste Text";
861 ot->description =
"Paste text from clipboard";
862 ot->idname =
"SEQUENCER_OT_text_edit_paste";
891 ot->name =
"Cut Text";
892 ot->description =
"Cut text to clipboard";
893 ot->idname =
"SEQUENCER_OT_text_edit_cut";
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
float BKE_scene_frame_get(const Scene *scene)
int char char int int int int size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
int BLI_str_utf8_size_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_strnlen_utf8_ex(const char *strc, size_t strc_maxlen, size_t *r_len_bytes) ATTR_NONNULL(1
@ SEQ_FLAG_TEXT_EDITING_ACTIVE
struct TextVarsRuntime TextVarsRuntime
bScreen * ED_screen_animation_no_scrub(const wmWindowManager *wm)
View2D * UI_view2d_fromcontext(const bContext *C)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
BMesh const char void * data
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
constexpr bool is_empty() const
float distance(VecOp< float, D >, VecOp< float, D >) RET
void MEM_freeN(void *vmemh)
blender::IndexRange strip_text_selection_range_get(const TextVars *data)
void SEQUENCER_OT_text_edit_copy(wmOperatorType *ot)
void SEQUENCER_OT_text_line_break(wmOperatorType *ot)
static bool text_insert(TextVars *data, const char *buf, const size_t buf_len)
static void cursor_set_by_mouse_position(const bContext *C, const wmEvent *event)
static wmOperatorStatus sequencer_text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SEQUENCER_OT_text_delete(wmOperatorType *ot)
void SEQUENCER_OT_text_edit_cut(wmOperatorType *ot)
static const EnumPropertyItem move_type_items[]
bool sequencer_text_editing_active_poll(bContext *C)
static wmOperatorStatus sequencer_text_edit_mode_toggle_exec(bContext *C, wmOperator *)
static const EnumPropertyItem delete_type_items[]
static void delete_character(const seq::CharInfo character, const TextVars *data)
static wmOperatorStatus sequencer_text_edit_paste_exec(bContext *C, wmOperator *)
void SEQUENCER_OT_text_insert(wmOperatorType *ot)
void SEQUENCER_OT_text_deselect_all(wmOperatorType *ot)
bool sequencer_editing_initialized_and_active(bContext *C)
static wmOperatorStatus sequencer_text_edit_copy_exec(bContext *C, wmOperator *)
static int2 cursor_move_by_line(int2 cursor_position, const TextVarsRuntime *text, int offset)
static void text_editing_update(const bContext *C)
static const seq::CharInfo & character_at_cursor_offset_get(const TextVarsRuntime *text, const int cursor_offset)
void SEQUENCER_OT_text_select_all(wmOperatorType *ot)
static wmOperatorStatus sequencer_text_deselect_all_exec(bContext *C, wmOperator *)
static int2 cursor_move_line_end(int2 cursor_position, const TextVarsRuntime *text)
static bool sequencer_text_editing_poll(bContext *C)
static wmOperatorStatus sequencer_text_cursor_move_exec(bContext *C, wmOperator *op)
static wmOperatorStatus sequencer_text_cursor_set_invoke(bContext *C, wmOperator *op, const wmEvent *event)
blender::int2 strip_text_cursor_offset_to_position(const TextVarsRuntime *text, int cursor_offset)
static wmOperatorStatus sequencer_text_delete_exec(bContext *C, wmOperator *op)
static void text_selection_cancel(TextVars *data)
static int2 cursor_move_next_word(int2 cursor_position, const TextVarsRuntime *text)
static int2 cursor_move_prev_word(int2 cursor_position, const TextVarsRuntime *text)
static bool is_whitespace_transition(char chr1, char chr2)
static wmOperatorStatus sequencer_text_insert_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_text_edit_paste(wmOperatorType *ot)
static void delete_selected_text(TextVars *data)
static int cursor_position_to_offset(const TextVarsRuntime *text, int2 cursor_position)
bool strip_point_image_isect(const Scene *scene, const Strip *strip, float point_view[2])
static const seq::CharInfo & character_at_cursor_pos_get(const TextVarsRuntime *text, const int2 cursor_pos)
static bool text_has_selection(const TextVars *data)
void SEQUENCER_OT_text_cursor_move(wmOperatorType *ot)
static int find_closest_cursor_offset(const TextVars *data, float2 mouse_loc)
static wmOperatorStatus sequencer_text_edit_cut_exec(bContext *C, wmOperator *)
static wmOperatorStatus sequencer_text_select_all_exec(bContext *C, wmOperator *)
static void text_edit_copy(const TextVars *data)
static wmOperatorStatus sequencer_text_line_break_exec(bContext *C, wmOperator *)
static int2 cursor_move_by_character(int2 cursor_position, const TextVarsRuntime *text, int offset)
void SEQUENCER_OT_text_cursor_set(wmOperatorType *ot)
void SEQUENCER_OT_text_edit_mode_toggle(wmOperatorType *ot)
static wmOperatorStatus sequencer_text_cursor_set_modal(bContext *C, wmOperator *, const wmEvent *event)
T distance(const T &a, const T &b)
T min(const T &a, const T &b)
CartesianBasis invert(const CartesianBasis &basis)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
float3x3 image_transform_matrix_get(const Scene *scene, const Strip *strip)
void relations_invalidate_cache_raw(Scene *scene, Strip *strip)
Strip * select_active_get(const Scene *scene)
bool time_strip_intersects_frame(const Scene *scene, const Strip *strip, const int timeline_frame)
bool effects_can_render_text(const Strip *strip)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
MatBase< float, 3, 3 > float3x3
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Vector< CharInfo > characters
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_clipboard_text_set(const char *buf, bool selection)
char * WM_clipboard_text_get(bool selection, bool ensure_utf8, int *r_len)