Blender V4.5
editfont.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cerrno>
11#include <cstdlib>
12#include <cstring>
13#include <cwchar>
14#include <fcntl.h>
15
16#include "MEM_guardedalloc.h"
17
18#include "BLI_fileops.h"
19#include "BLI_listbase.h"
20#include "BLI_math_geom.h"
21#include "BLI_math_matrix.h"
22#include "BLI_math_vector.h"
23#include "BLI_path_utils.hh"
24#include "BLI_string.h"
26#include "BLI_utildefines.h"
27
28#include "DNA_curve_types.h"
29#include "DNA_object_types.h"
30#include "DNA_scene_types.h"
31#include "DNA_text_types.h"
32#include "DNA_vfont_types.h"
33
34#include "BKE_context.hh"
35#include "BKE_curve.hh"
36#include "BKE_global.hh"
37#include "BKE_layer.hh"
38#include "BKE_lib_id.hh"
39#include "BKE_library.hh"
40#include "BKE_main.hh"
41#include "BKE_object.hh"
42#include "BKE_report.hh"
43#include "BKE_vfont.hh"
44
45#include "BLI_string_utf8.h"
46
47#include "BLT_translation.hh"
48
49#include "DEG_depsgraph.hh"
51
52#include "RNA_access.hh"
53#include "RNA_define.hh"
54
55#include "WM_api.hh"
56#include "WM_types.hh"
57
58#include "ED_curve.hh"
59#include "ED_object.hh"
60#include "ED_outliner.hh"
61#include "ED_screen.hh"
62#include "ED_view3d.hh"
63
64#include "UI_interface.hh"
65
66#include "curve_intern.hh"
67
68#define MAXTEXT 32766
69
70static int kill_selection(Object *obedit, int ins);
71static char *font_select_to_buffer(Object *obedit);
72
73/* -------------------------------------------------------------------- */
76
77static char32_t findaccent(char32_t char1, const char code)
78{
79 char32_t new_char = 0;
80
81 if (char1 == 'a') {
82 if (code == '`') {
83 new_char = 224;
84 }
85 else if (code == 39) {
86 new_char = 225;
87 }
88 else if (code == '^') {
89 new_char = 226;
90 }
91 else if (code == '~') {
92 new_char = 227;
93 }
94 else if (code == '"') {
95 new_char = 228;
96 }
97 else if (code == 'o') {
98 new_char = 229;
99 }
100 else if (code == 'e') {
101 new_char = 230;
102 }
103 else if (code == '-') {
104 new_char = 170;
105 }
106 }
107 else if (char1 == 'c') {
108 if (code == ',') {
109 new_char = 231;
110 }
111 else if (code == '|') {
112 new_char = 162;
113 }
114 else if (code == 'o') {
115 new_char = 169;
116 }
117 }
118 else if (char1 == 'e') {
119 if (code == '`') {
120 new_char = 232;
121 }
122 else if (code == 39) {
123 new_char = 233;
124 }
125 else if (code == '^') {
126 new_char = 234;
127 }
128 else if (code == '"') {
129 new_char = 235;
130 }
131 }
132 else if (char1 == 'i') {
133 if (code == '`') {
134 new_char = 236;
135 }
136 else if (code == 39) {
137 new_char = 237;
138 }
139 else if (code == '^') {
140 new_char = 238;
141 }
142 else if (code == '"') {
143 new_char = 239;
144 }
145 }
146 else if (char1 == 'n') {
147 if (code == '~') {
148 new_char = 241;
149 }
150 }
151 else if (char1 == 'o') {
152 if (code == '`') {
153 new_char = 242;
154 }
155 else if (code == 39) {
156 new_char = 243;
157 }
158 else if (code == '^') {
159 new_char = 244;
160 }
161 else if (code == '~') {
162 new_char = 245;
163 }
164 else if (code == '"') {
165 new_char = 246;
166 }
167 else if (code == '/') {
168 new_char = 248;
169 }
170 else if (code == '-') {
171 new_char = 186;
172 }
173 else if (code == 'e') {
174 new_char = 339;
175 }
176 else if (code == 'c') {
177 new_char = 169;
178 }
179 else if (code == 'r') {
180 new_char = 174;
181 }
182 }
183 else if (char1 == 'r') {
184 if (code == 'o') {
185 new_char = 174;
186 }
187 }
188 else if (char1 == 's') {
189 if (code == 's') {
190 new_char = 167;
191 }
192 }
193 else if (char1 == 't') {
194 if (code == 'm') {
195 new_char = 8482;
196 }
197 }
198 else if (char1 == 'u') {
199 if (code == '`') {
200 new_char = 249;
201 }
202 else if (code == 39) {
203 new_char = 250;
204 }
205 else if (code == '^') {
206 new_char = 251;
207 }
208 else if (code == '"') {
209 new_char = 252;
210 }
211 }
212 else if (char1 == 'y') {
213 if (code == 39) {
214 new_char = 253;
215 }
216 else if (code == '"') {
217 new_char = 255;
218 }
219 }
220 else if (char1 == 'A') {
221 if (code == '`') {
222 new_char = 192;
223 }
224 else if (code == 39) {
225 new_char = 193;
226 }
227 else if (code == '^') {
228 new_char = 194;
229 }
230 else if (code == '~') {
231 new_char = 195;
232 }
233 else if (code == '"') {
234 new_char = 196;
235 }
236 else if (code == 'o') {
237 new_char = 197;
238 }
239 else if (code == 'e') {
240 new_char = 198;
241 }
242 }
243 else if (char1 == 'C') {
244 if (code == ',') {
245 new_char = 199;
246 }
247 }
248 else if (char1 == 'E') {
249 if (code == '`') {
250 new_char = 200;
251 }
252 else if (code == 39) {
253 new_char = 201;
254 }
255 else if (code == '^') {
256 new_char = 202;
257 }
258 else if (code == '"') {
259 new_char = 203;
260 }
261 }
262 else if (char1 == 'I') {
263 if (code == '`') {
264 new_char = 204;
265 }
266 else if (code == 39) {
267 new_char = 205;
268 }
269 else if (code == '^') {
270 new_char = 206;
271 }
272 else if (code == '"') {
273 new_char = 207;
274 }
275 }
276 else if (char1 == 'N') {
277 if (code == '~') {
278 new_char = 209;
279 }
280 }
281 else if (char1 == 'O') {
282 if (code == '`') {
283 new_char = 210;
284 }
285 else if (code == 39) {
286 new_char = 211;
287 }
288 else if (code == '^') {
289 new_char = 212;
290 }
291 else if (code == '~') {
292 new_char = 213;
293 }
294 else if (code == '"') {
295 new_char = 214;
296 }
297 else if (code == '/') {
298 new_char = 216;
299 }
300 else if (code == 'e') {
301 new_char = 141;
302 }
303 }
304 else if (char1 == 'U') {
305 if (code == '`') {
306 new_char = 217;
307 }
308 else if (code == 39) {
309 new_char = 218;
310 }
311 else if (code == '^') {
312 new_char = 219;
313 }
314 else if (code == '"') {
315 new_char = 220;
316 }
317 }
318 else if (char1 == 'Y') {
319 if (code == 39) {
320 new_char = 221;
321 }
322 }
323 else if (char1 == '1') {
324 if (code == '4') {
325 new_char = 188;
326 }
327 if (code == '2') {
328 new_char = 189;
329 }
330 }
331 else if (char1 == '3') {
332 if (code == '4') {
333 new_char = 190;
334 }
335 }
336 else if (char1 == ':') {
337 if (code == '-') {
338 new_char = 247;
339 }
340 }
341 else if (char1 == '-') {
342 if (code == ':') {
343 new_char = 247;
344 }
345 if (code == '|') {
346 new_char = 8224;
347 }
348 if (code == '+') {
349 new_char = 177;
350 }
351 }
352 else if (char1 == '|') {
353 if (code == '-') {
354 new_char = 8224;
355 }
356 if (code == '=') {
357 new_char = 8225;
358 }
359 }
360 else if (char1 == '=') {
361 if (code == '|') {
362 new_char = 8225;
363 }
364 }
365 else if (char1 == '+') {
366 if (code == '-') {
367 new_char = 177;
368 }
369 }
370
371 if (new_char) {
372 return new_char;
373 }
374 return char1;
375}
376
377static int insert_into_textbuf(Object *obedit, uintptr_t c)
378{
379 Curve *cu = static_cast<Curve *>(obedit->data);
380 EditFont *ef = cu->editfont;
381
382 if (ef->len < MAXTEXT - 1) {
383 int x;
384
385 for (x = ef->len; x > ef->pos; x--) {
386 ef->textbuf[x] = ef->textbuf[x - 1];
387 }
388 for (x = ef->len; x > ef->pos; x--) {
389 ef->textbufinfo[x] = ef->textbufinfo[x - 1];
390 }
391 ef->textbuf[ef->pos] = c;
392 ef->textbufinfo[ef->pos] = cu->curinfo;
393 ef->textbufinfo[ef->pos].kern = 0.0f;
394 ef->textbufinfo[ef->pos].mat_nr = obedit->actcol - 1;
395
396 ef->pos++;
397 ef->len++;
398 ef->textbuf[ef->len] = '\0';
399
400 return 1;
401 }
402 return 0;
403}
404
405static void text_update_edited(bContext *C, Object *obedit, const eEditFontMode mode)
406{
407 Curve *cu = static_cast<Curve *>(obedit->data);
408 EditFont *ef = cu->editfont;
409
410 BLI_assert(ef->len >= 0);
411
412 /* Run update first since it can move the cursor. */
413 if (mode == FO_EDIT) {
414 /* Re-tessellate. */
415 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
416 }
417 else {
418 /* Depsgraph runs above, but since we're not tagging for update, call directly. */
419 /* We need evaluated data here. */
422 }
423
424 cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
425
427
428 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_SELECT);
430}
431
432static int kill_selection(Object *obedit, int ins) /* ins == new character len */
433{
434 Curve *cu = static_cast<Curve *>(obedit->data);
435 EditFont *ef = cu->editfont;
436 int selend, selstart, direction;
437 int getfrom;
438
439 direction = BKE_vfont_select_get(cu, &selstart, &selend);
440 if (direction) {
441 int size;
442 if (ef->pos >= selstart) {
443 ef->pos = selstart + ins;
444 }
445 if ((direction == -1) && ins) {
446 selstart += ins;
447 selend += ins;
448 }
449 getfrom = selend + 1;
450 size = ef->len - selend; /* This is equivalent to: `(ef->len - getfrom) + 1(null)`. */
451 memmove(ef->textbuf + selstart, ef->textbuf + getfrom, sizeof(*ef->textbuf) * size);
452 memmove(ef->textbufinfo + selstart, ef->textbufinfo + getfrom, sizeof(CharInfo) * size);
453 ef->len -= ((selend - selstart) + 1);
454 ef->selstart = ef->selend = 0;
455 }
456
457 return direction;
458}
459
461{
462 if (G.background) {
463 return;
464 }
465
467 return;
468 }
469 char *buf = font_select_to_buffer(obedit);
470 if (buf == nullptr) {
471 return;
472 }
473 WM_clipboard_text_set(buf, true);
474 MEM_freeN(buf);
475}
476
478
479/* -------------------------------------------------------------------- */
482
483static bool font_paste_wchar(Object *obedit,
484 const char32_t *str,
485 const size_t str_len,
486 /* Optional. */
487 const CharInfo *str_info)
488{
489 Curve *cu = static_cast<Curve *>(obedit->data);
490 EditFont *ef = cu->editfont;
491 int selend, selstart;
492
493 if (BKE_vfont_select_get(cu, &selstart, &selend) == 0) {
494 selstart = selend = 0;
495 }
496
497 /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */
498 if ((ef->len + str_len) - (selend - selstart) <= MAXTEXT) {
499
500 kill_selection(obedit, 0);
501
502 if (str_len) {
503 int size = (ef->len * sizeof(*ef->textbuf)) - (ef->pos * sizeof(*ef->textbuf)) +
504 sizeof(*ef->textbuf);
505 memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size);
506 memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(*ef->textbuf));
507
508 memmove(ef->textbufinfo + ef->pos + str_len,
509 ef->textbufinfo + ef->pos,
510 (ef->len - ef->pos + 1) * sizeof(CharInfo));
511 if (str_info) {
512 const short mat_nr_max = std::max(0, obedit->totcol - 1);
513 const CharInfo *info_src = str_info;
514 CharInfo *info_dst = ef->textbufinfo + ef->pos;
515
516 for (int i = 0; i < str_len; i++, info_src++, info_dst++) {
517 *info_dst = *info_src;
518 CLAMP_MAX(info_dst->mat_nr, mat_nr_max);
519 }
520 }
521 else {
522 std::fill_n(ef->textbufinfo + ef->pos, str_len, CharInfo{});
523 }
524
525 ef->len += str_len;
526 ef->pos += str_len;
527 }
528
529 return true;
530 }
531
532 return false;
533}
534
535static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
536{
537 Object *obedit = CTX_data_edit_object(C);
538 bool retval;
539
540 int tmplen;
541
542 char32_t *mem = MEM_malloc_arrayN<char32_t>(str_len + 1, __func__);
543
544 tmplen = BLI_str_utf8_as_utf32(mem, str, str_len + 1);
545
546 retval = font_paste_wchar(obedit, mem, tmplen, nullptr);
547
548 MEM_freeN(mem);
549
550 return retval;
551}
552
554
555/* -------------------------------------------------------------------- */
558
559static char *font_select_to_buffer(Object *obedit)
560{
561 Curve *cu = static_cast<Curve *>(obedit->data);
562 int selstart, selend;
563 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
564 return nullptr;
565 }
566 EditFont *ef = cu->editfont;
567 const char32_t *text_buf = ef->textbuf + selstart;
568 const size_t text_buf_len = selend - selstart;
569
570 const size_t len_utf8 = BLI_str_utf32_as_utf8_len_ex(text_buf, text_buf_len + 1);
571 char *buf = MEM_malloc_arrayN<char>(len_utf8 + 1, __func__);
572 BLI_str_utf32_as_utf8(buf, text_buf, len_utf8);
573 return buf;
574}
575
577
578/* -------------------------------------------------------------------- */
581
583{
584 Object *obedit = CTX_data_edit_object(C);
585 char *strp;
586 size_t filelen;
587 wmOperatorStatus retval;
588
589 strp = static_cast<char *>(BLI_file_read_text_as_mem(filepath, 1, &filelen));
590 if (strp == nullptr) {
591 BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filepath);
592 return OPERATOR_CANCELLED;
593 }
594 strp[filelen] = 0;
595
596 if (font_paste_utf8(C, strp, filelen)) {
597 text_update_edited(C, obedit, FO_EDIT);
598 retval = OPERATOR_FINISHED;
599 }
600 else {
601 BKE_reportf(reports, RPT_ERROR, "File too long %s", filepath);
602 retval = OPERATOR_CANCELLED;
603 }
604
605 MEM_freeN(strp);
606
607 return retval;
608}
609
611{
612 char *filepath;
613 wmOperatorStatus retval;
614
615 filepath = RNA_string_get_alloc(op->ptr, "filepath", nullptr, 0, nullptr);
616 retval = paste_from_file(C, op->reports, filepath);
617 MEM_freeN(filepath);
618
619 return retval;
620}
621
623 wmOperator *op,
624 const wmEvent * /*event*/)
625{
626 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
627 return paste_from_file_exec(C, op);
628 }
629
631
633}
634
636{
637 /* identifiers */
638 ot->name = "Paste File";
639 ot->description = "Paste contents from file";
640 ot->idname = "FONT_OT_text_paste_from_file";
641
642 /* API callbacks. */
643 ot->exec = paste_from_file_exec;
644 ot->invoke = paste_from_file_invoke;
645 ot->poll = ED_operator_editfont;
646
647 /* flags */
649
650 /* properties */
658}
659
661
662/* -------------------------------------------------------------------- */
665
666static void text_insert_unicode_cancel(bContext *C, void *arg_block, void * /*arg2*/)
667{
668 uiBlock *block = static_cast<uiBlock *>(arg_block);
670}
671
672static void text_insert_unicode_confirm(bContext *C, void *arg_block, void *arg_string)
673{
674 uiBlock *block = static_cast<uiBlock *>(arg_block);
675 char *edit_string = static_cast<char *>(arg_string);
676
677 if (edit_string[0] == 0) {
678 /* Blank text is probably purposeful closure. */
680 return;
681 }
682
683 uint val = strtoul(edit_string, nullptr, 16);
684 if (val > 31 && val < 0x10FFFF) {
685 Object *obedit = CTX_data_edit_object(C);
686 if (obedit) {
687 const char32_t utf32[2] = {val, 0};
688 font_paste_wchar(obedit, utf32, 1, nullptr);
689 text_update_edited(C, obedit, FO_EDIT);
690 }
692 }
693 else {
694 /* Invalid. Clear text and keep dialog open. */
695 edit_string[0] = 0;
696 }
697}
698
699static uiBlock *wm_block_insert_unicode_create(bContext *C, ARegion *region, void *arg_string)
700{
701 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
702 char *edit_string = static_cast<char *>(arg_string);
703
706 const uiStyle *style = UI_style_get_dpi();
707 uiLayout *layout = UI_block_layout(
708 block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200 * UI_SCALE_FAC, UI_UNIT_Y, 0, style);
709
710 uiItemL_ex(layout, IFACE_("Insert Unicode Character"), ICON_NONE, true, false);
711 layout->label(RPT_("Enter a Unicode codepoint hex value"), ICON_NONE);
712
713 uiBut *text_but = uiDefBut(block,
715 0,
716 "",
717 0,
718 0,
719 100,
720 UI_UNIT_Y,
721 edit_string,
722 0,
723 7,
724 TIP_("Unicode codepoint hex value"));
726 /* Hitting Enter in the text input is treated the same as clicking the Confirm button. */
727 UI_but_func_set(text_but, text_insert_unicode_confirm, block, edit_string);
728
729 layout->separator();
730
731 /* Buttons. */
732
733#ifdef _WIN32
734 const bool windows_layout = true;
735#else
736 const bool windows_layout = false;
737#endif
738
739 uiBut *confirm = nullptr;
740 uiBut *cancel = nullptr;
741 uiLayout *split = &layout->split(0.0f, true);
742 split->column(false);
743
744 if (windows_layout) {
745 confirm = uiDefIconTextBut(block,
747 0,
748 0,
749 IFACE_("Insert"),
750 0,
751 0,
752 0,
753 UI_UNIT_Y,
754 nullptr,
755 0,
756 0,
757 std::nullopt);
758 split->column(false);
759 }
760
761 cancel = uiDefIconTextBut(block,
763 0,
764 0,
765 IFACE_("Cancel"),
766 0,
767 0,
768 0,
769 UI_UNIT_Y,
770 nullptr,
771 0,
772 0,
773 std::nullopt);
774
775 if (!windows_layout) {
776 split->column(false);
777 confirm = uiDefIconTextBut(block,
779 0,
780 0,
781 IFACE_("Insert"),
782 0,
783 0,
784 0,
785 UI_UNIT_Y,
786 nullptr,
787 0,
788 0,
789 std::nullopt);
790 }
791
792 UI_block_func_set(block, nullptr, nullptr, nullptr);
793 UI_but_func_set(confirm, text_insert_unicode_confirm, block, edit_string);
794 UI_but_func_set(cancel, text_insert_unicode_cancel, block, nullptr);
798
799 int bounds_offset[2];
800 bounds_offset[0] = uiLayoutGetWidth(layout) * -0.2f;
801 bounds_offset[1] = UI_UNIT_Y * 2.5;
802 UI_block_bounds_set_popup(block, 7 * UI_SCALE_FAC, bounds_offset);
803
804 return block;
805}
806
808 wmOperator * /*op*/,
809 const wmEvent * /*event*/)
810{
811 char *edit_string = MEM_malloc_arrayN<char>(24, __func__);
812 edit_string[0] = 0;
814 return OPERATOR_FINISHED;
815}
816
818{
819 /* identifiers */
820 ot->name = "Insert Unicode";
821 ot->description = "Insert Unicode Character";
822 ot->idname = "FONT_OT_text_insert_unicode";
823
824 /* API callbacks. */
826 ot->poll = ED_operator_editfont;
827
828 /* flags */
830}
831
833
834/* -------------------------------------------------------------------- */
837
839 const TextLine *firstline,
840 int totline,
841 const float offset[3])
842{
843 Main *bmain = CTX_data_main(C);
845 Scene *scene = CTX_data_scene(C);
846 ViewLayer *view_layer = CTX_data_view_layer(C);
847 Curve *cu;
848 Object *obedit;
849 Object *object;
850 const TextLine *tmp;
851 int nchars = 0, nbytes = 0;
852 char *s;
853 int a;
854 const float rot[3] = {0.0f, 0.0f, 0.0f};
855
856 obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, nullptr);
857 BKE_view_layer_synced_ensure(scene, view_layer);
858 object = BKE_view_layer_active_object_get(view_layer);
859
860 /* seems to assume view align ? TODO: look into this, could be an operator option. */
862
863 BKE_object_where_is_calc(depsgraph, scene, obedit);
864
865 add_v3_v3(obedit->loc, offset);
866
867 cu = static_cast<Curve *>(obedit->data);
869 id_us_plus(&cu->vfont->id);
870
871 for (tmp = firstline, a = 0; nbytes < MAXTEXT && a < totline; tmp = tmp->next, a++) {
872 size_t nchars_line, nbytes_line;
873 nchars_line = BLI_strlen_utf8_ex(tmp->line, &nbytes_line);
874 nchars += nchars_line + 1;
875 nbytes += nbytes_line + 1;
876 }
877
878 if (cu->str) {
879 MEM_freeN(cu->str);
880 }
881 if (cu->strinfo) {
882 MEM_freeN(cu->strinfo);
883 }
884
885 cu->str = MEM_malloc_arrayN<char>(nbytes + 4, "str");
886 cu->strinfo = MEM_calloc_arrayN<CharInfo>((nchars + 4), "strinfo");
887
888 cu->len = 0;
889 cu->len_char32 = nchars - 1;
890 cu->pos = 0;
891
892 s = cu->str;
893
894 for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) {
895 size_t nchars_line_dummy, nbytes_line;
896 nchars_line_dummy = BLI_strlen_utf8_ex(tmp->line, &nbytes_line);
897 (void)nchars_line_dummy;
898
899 memcpy(s, tmp->line, nbytes_line);
900 s += nbytes_line;
901 cu->len += nbytes_line;
902
903 if (tmp->next) {
904 *s = '\n';
905 s += 1;
906 cu->len += 1;
907 }
908 }
909
910 cu->pos = cu->len_char32;
911 *s = '\0';
912
914}
915
916void ED_text_to_object(bContext *C, const Text *text, const bool split_lines)
917{
918 Main *bmain = CTX_data_main(C);
920 float offset[3];
921 int linenum = 0;
922
923 if (!text || !text->lines.first) {
924 return;
925 }
926
927 if (split_lines) {
928 LISTBASE_FOREACH (const TextLine *, line, &text->lines) {
929 /* skip lines with no text, but still make space for them */
930 if (line->line[0] == '\0') {
931 linenum++;
932 continue;
933 }
934
935 /* do the translation */
936 offset[0] = 0;
937 offset[1] = -linenum;
938 offset[2] = 0;
939
940 if (rv3d) {
941 mul_mat3_m4_v3(rv3d->viewinv, offset);
942 }
943
944 txt_add_object(C, line, 1, offset);
945
946 linenum++;
947 }
948 }
949 else {
950 offset[0] = 0.0f;
951 offset[1] = 0.0f;
952 offset[2] = 0.0f;
953
955 static_cast<const TextLine *>(text->lines.first),
957 offset);
958 }
959
962}
963
965
966/* -------------------------------------------------------------------- */
969
971 {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""},
972 {CU_CHINFO_ITALIC, "ITALIC", 0, "Italic", ""},
973 {CU_CHINFO_UNDERLINE, "UNDERLINE", 0, "Underline", ""},
974 {CU_CHINFO_SMALLCAPS, "SMALL_CAPS", 0, "Small Caps", ""},
975 {0, nullptr, 0, nullptr, nullptr},
976};
977
978static wmOperatorStatus set_style(bContext *C, const int style, const bool clear)
979{
980 Object *obedit = CTX_data_edit_object(C);
981 Curve *cu = static_cast<Curve *>(obedit->data);
982 EditFont *ef = cu->editfont;
983 int i, selstart, selend;
984
985 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
986 return OPERATOR_CANCELLED;
987 }
988
989 for (i = selstart; i <= selend; i++) {
990 if (clear) {
991 ef->textbufinfo[i].flag &= ~style;
992 }
993 else {
994 ef->textbufinfo[i].flag |= style;
995 }
996 }
997
998 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
1000
1001 return OPERATOR_FINISHED;
1002}
1003
1005{
1006 const int style = RNA_enum_get(op->ptr, "style");
1007 const bool clear = RNA_boolean_get(op->ptr, "clear");
1008
1009 return set_style(C, style, clear);
1010}
1011
1013{
1014 /* identifiers */
1015 ot->name = "Set Style";
1016 ot->description = "Set font style";
1017 ot->idname = "FONT_OT_style_set";
1018
1019 /* API callbacks. */
1020 ot->exec = set_style_exec;
1021 ot->poll = ED_operator_editfont;
1022
1023 /* flags */
1024 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1025
1026 /* properties */
1028 ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
1029 RNA_def_boolean(ot->srna, "clear", false, "Clear", "Clear style rather than setting it");
1030}
1031
1033
1034/* -------------------------------------------------------------------- */
1037
1039{
1040 Object *obedit = CTX_data_edit_object(C);
1041 Curve *cu = static_cast<Curve *>(obedit->data);
1042 int style, clear, selstart, selend;
1043
1044 style = RNA_enum_get(op->ptr, "style");
1045 cu->curinfo.flag ^= style;
1046 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
1047 clear = (cu->curinfo.flag & style) == 0;
1048 return set_style(C, style, clear);
1049 }
1050 return OPERATOR_CANCELLED;
1051}
1052
1054{
1055 /* identifiers */
1056 ot->name = "Toggle Style";
1057 ot->description = "Toggle font style";
1058 ot->idname = "FONT_OT_style_toggle";
1059
1060 /* API callbacks. */
1061 ot->exec = toggle_style_exec;
1062 ot->poll = ED_operator_editfont;
1063
1064 /* flags */
1065 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1066
1067 /* properties */
1069 ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
1070}
1071
1073
1074/* -------------------------------------------------------------------- */
1077
1079{
1080 Object *obedit = CTX_data_edit_object(C);
1081 Curve *cu = static_cast<Curve *>(obedit->data);
1082 EditFont *ef = cu->editfont;
1083
1084 if (ef->len) {
1085 ef->selstart = 1;
1086 ef->selend = ef->len;
1087 ef->pos = ef->len;
1088
1091
1092 return OPERATOR_FINISHED;
1093 }
1094 return OPERATOR_CANCELLED;
1095}
1096
1098{
1099 /* identifiers */
1100 ot->name = "Select All";
1101 ot->description = "Select all text";
1102 ot->idname = "FONT_OT_select_all";
1103
1104 /* API callbacks. */
1105 ot->exec = font_select_all_exec;
1106 ot->poll = ED_operator_editfont;
1107
1108 /* flags */
1109 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1110}
1111
1113
1114/* -------------------------------------------------------------------- */
1117
1118static void copy_selection(Object *obedit)
1119{
1120 Curve *cu = static_cast<Curve *>(obedit->data);
1121 int selstart, selend;
1122
1123 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
1124 EditFont *ef = cu->editfont;
1125 char *buf = nullptr;
1126 char32_t *text_buf;
1127 size_t len_utf8;
1128
1129 /* internal clipboard (for style) */
1131 ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1);
1132 BKE_vfont_clipboard_get(&text_buf, nullptr, &len_utf8, nullptr);
1133
1134 /* system clipboard */
1135 buf = MEM_malloc_arrayN<char>(len_utf8 + 1, __func__);
1136 if (buf) {
1137 BLI_str_utf32_as_utf8(buf, text_buf, len_utf8 + 1);
1138 WM_clipboard_text_set(buf, false);
1139 MEM_freeN(buf);
1140 }
1141 }
1142}
1143
1145{
1146 Object *obedit = CTX_data_edit_object(C);
1147
1148 copy_selection(obedit);
1149
1150 return OPERATOR_FINISHED;
1151}
1152
1154{
1155 /* identifiers */
1156 ot->name = "Copy Text";
1157 ot->description = "Copy selected text to clipboard";
1158 ot->idname = "FONT_OT_text_copy";
1159
1160 /* API callbacks. */
1161 ot->exec = copy_text_exec;
1162 ot->poll = ED_operator_editfont;
1163}
1164
1166
1167/* -------------------------------------------------------------------- */
1170
1172{
1173 Object *obedit = CTX_data_edit_object(C);
1174 Curve *cu = static_cast<Curve *>(obedit->data);
1175 int selstart, selend;
1176
1177 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
1178 return OPERATOR_CANCELLED;
1179 }
1180
1181 copy_selection(obedit);
1182 kill_selection(obedit, 0);
1183
1184 text_update_edited(C, obedit, FO_EDIT);
1185
1186 return OPERATOR_FINISHED;
1187}
1188
1190{
1191 /* identifiers */
1192 ot->name = "Cut Text";
1193 ot->description = "Cut selected text to clipboard";
1194 ot->idname = "FONT_OT_text_cut";
1195
1196 /* API callbacks. */
1197 ot->exec = cut_text_exec;
1198 ot->poll = ED_operator_editfont;
1199
1200 /* flags */
1201 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1202}
1203
1205
1206/* -------------------------------------------------------------------- */
1209
1211{
1212 char32_t *text_buf;
1213 CharInfo *info_buf;
1214 size_t len;
1215
1216 BKE_vfont_clipboard_get(&text_buf, &info_buf, nullptr, &len);
1217
1218 if (font_paste_wchar(obedit, text_buf, len, info_buf)) {
1219 return true;
1220 }
1221
1222 BKE_report(reports, RPT_WARNING, "Text too long");
1223 return false;
1224}
1225
1227{
1228 const bool selection = RNA_boolean_get(op->ptr, "selection");
1229 Object *obedit = CTX_data_edit_object(C);
1230 wmOperatorStatus retval;
1231 size_t len_utf8;
1232 char32_t *text_buf;
1233
1234 /* Store both clipboards as UTF8 for comparison,
1235 * Give priority to the internal `vfont` clipboard with its #CharInfo text styles
1236 * as long as its synchronized with the systems clipboard. */
1237 struct {
1238 char *buf;
1239 int len;
1240 } clipboard_system = {nullptr}, clipboard_vfont = {nullptr};
1241
1242 /* No need for UTF8 validation as the conversion handles invalid sequences gracefully. */
1243 clipboard_system.buf = WM_clipboard_text_get(selection, false, &clipboard_system.len);
1244
1245 if (clipboard_system.buf == nullptr) {
1246 return OPERATOR_CANCELLED;
1247 }
1248
1249 BKE_vfont_clipboard_get(&text_buf, nullptr, &len_utf8, nullptr);
1250
1251 if (text_buf) {
1252 clipboard_vfont.buf = MEM_malloc_arrayN<char>(len_utf8 + 1, __func__);
1253
1254 if (clipboard_vfont.buf == nullptr) {
1255 MEM_freeN(clipboard_system.buf);
1256 return OPERATOR_CANCELLED;
1257 }
1258
1259 BLI_str_utf32_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
1260 }
1261
1262 if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
1264 }
1265 else {
1266 if ((clipboard_system.len <= MAXTEXT) &&
1267 font_paste_utf8(C, clipboard_system.buf, clipboard_system.len))
1268 {
1269 text_update_edited(C, obedit, FO_EDIT);
1270 retval = OPERATOR_FINISHED;
1271 }
1272 else {
1273 BKE_report(op->reports, RPT_ERROR, "Clipboard too long");
1274 retval = OPERATOR_CANCELLED;
1275 }
1276
1277 /* free the existent clipboard buffer */
1279 }
1280
1281 if (retval != OPERATOR_CANCELLED) {
1282 text_update_edited(C, obedit, FO_EDIT);
1283 }
1284
1285 /* cleanup */
1286 if (clipboard_vfont.buf) {
1287 MEM_freeN(clipboard_vfont.buf);
1288 }
1289
1290 MEM_freeN(clipboard_system.buf);
1291
1292 return retval;
1293}
1294
1296{
1297 /* identifiers */
1298 ot->name = "Paste Text";
1299 ot->description = "Paste text from clipboard";
1300 ot->idname = "FONT_OT_text_paste";
1301
1302 /* API callbacks. */
1303 ot->exec = paste_text_exec;
1304 ot->poll = ED_operator_editfont;
1305
1306 /* flags */
1307 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1308
1309 /* properties */
1310 PropertyRNA *prop;
1311 prop = RNA_def_boolean(ot->srna,
1312 "selection",
1313 false,
1314 "Selection",
1315 "Paste text selected elsewhere rather than copied (X11/Wayland only)");
1317}
1318
1320
1321/* -------------------------------------------------------------------- */
1324
1326 {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
1327 {LINE_END, "LINE_END", 0, "Line End", ""},
1328 {TEXT_BEGIN, "TEXT_BEGIN", 0, "Text Begin", ""},
1329 {TEXT_END, "TEXT_END", 0, "Text End", ""},
1330 {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
1331 {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
1332 {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
1333 {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
1334 {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""},
1335 {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""},
1336 {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""},
1337 {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""},
1338 {0, nullptr, 0, nullptr, nullptr},
1339};
1340
1346static bool move_cursor_drop_select(Object *obedit, int dir)
1347{
1348 Curve *cu = static_cast<Curve *>(obedit->data);
1349 int selstart, selend;
1350 if (!BKE_vfont_select_get(cu, &selstart, &selend)) {
1351 return false;
1352 }
1353
1354 EditFont *ef = cu->editfont;
1355 if (dir == -1) {
1356 ef->pos = selstart;
1357 }
1358 else if (dir == 1) {
1359 ef->pos = selend + 1;
1360 }
1361 else {
1363 }
1364
1365 /* The caller must clear the selection. */
1366 return true;
1367}
1368
1369static wmOperatorStatus move_cursor(bContext *C, int type, const bool select)
1370{
1372 Object *obedit = CTX_data_edit_object(C);
1373 Curve *cu = static_cast<Curve *>(obedit->data);
1374 EditFont *ef = cu->editfont;
1375 int cursmove = -1;
1376
1377 if ((select) && (ef->selstart == 0)) {
1378 ef->selstart = ef->selend = ef->pos + 1;
1379 }
1380
1381 switch (type) {
1382 case LINE_BEGIN:
1383 cursmove = FO_LINE_BEGIN;
1384 break;
1385 case LINE_END:
1386 cursmove = FO_LINE_END;
1387 break;
1388
1389 case TEXT_BEGIN:
1390 ef->pos = 0;
1391 cursmove = FO_CURS;
1392 break;
1393
1394 case TEXT_END:
1395 ef->pos = ef->len;
1396 cursmove = FO_CURS;
1397 break;
1398
1399 case PREV_WORD: {
1400 if ((select == false) && move_cursor_drop_select(obedit, -1)) {
1401 cursmove = FO_CURS;
1402 }
1403 else {
1404 int pos = ef->pos;
1406 ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
1407 ef->pos = pos;
1408 cursmove = FO_CURS;
1409 }
1410 break;
1411 }
1412
1413 case NEXT_WORD: {
1414 if ((select == false) && move_cursor_drop_select(obedit, 1)) {
1415 cursmove = FO_CURS;
1416 }
1417 else {
1418 int pos = ef->pos;
1420 ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
1421 ef->pos = pos;
1422 cursmove = FO_CURS;
1423 }
1424 break;
1425 }
1426
1427 case PREV_CHAR: {
1428 if ((select == false) && move_cursor_drop_select(obedit, -1)) {
1429 cursmove = FO_CURS;
1430 }
1431 else {
1433 cursmove = FO_CURS;
1434 }
1435 break;
1436 }
1437 case NEXT_CHAR: {
1438 if ((select == false) && move_cursor_drop_select(obedit, 1)) {
1439 cursmove = FO_CURS;
1440 }
1441 else {
1443 cursmove = FO_CURS;
1444 }
1445 break;
1446 }
1447 case PREV_LINE:
1448 cursmove = FO_CURSUP;
1449 break;
1450
1451 case NEXT_LINE:
1452 cursmove = FO_CURSDOWN;
1453 break;
1454
1455 case PREV_PAGE:
1456 cursmove = FO_PAGEUP;
1457 break;
1458
1459 case NEXT_PAGE:
1460 cursmove = FO_PAGEDOWN;
1461 break;
1462 }
1463
1464 if (cursmove == -1) {
1465 return OPERATOR_CANCELLED;
1466 }
1467
1468 if (ef->pos > ef->len) {
1469 ef->pos = ef->len;
1470 }
1471 else if (ef->pos >= MAXTEXT) {
1472 ef->pos = MAXTEXT;
1473 }
1474 else if (ef->pos < 0) {
1475 ef->pos = 0;
1476 }
1477
1478 /* apply vertical cursor motion to position immediately
1479 * otherwise the selection will lag behind */
1480 if (FO_CURS_IS_MOTION(cursmove)) {
1482 cursmove = FO_CURS;
1483 }
1484
1485 if (select == 0) {
1486 if (ef->selstart) {
1487 ef->selstart = ef->selend = 0;
1489 }
1490 }
1491
1492 if (select) {
1493 ef->selend = ef->pos;
1495 }
1496
1497 text_update_edited(C, obedit, eEditFontMode(cursmove));
1498
1499 return OPERATOR_FINISHED;
1500}
1501
1503{
1504 int type = RNA_enum_get(op->ptr, "type");
1505
1506 return move_cursor(C, type, false);
1507}
1508
1510{
1511 /* identifiers */
1512 ot->name = "Move Cursor";
1513 ot->description = "Move cursor to position type";
1514 ot->idname = "FONT_OT_move";
1515
1516 /* API callbacks. */
1517 ot->exec = move_exec;
1518 ot->poll = ED_operator_editfont;
1519
1520 /* flags */
1521 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1522
1523 /* properties */
1524 RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
1525}
1526
1528
1529/* -------------------------------------------------------------------- */
1532
1534{
1535 int type = RNA_enum_get(op->ptr, "type");
1536
1537 return move_cursor(C, type, true);
1538}
1539
1541{
1542 /* identifiers */
1543 ot->name = "Move Select";
1544 ot->description = "Move the cursor while selecting";
1545 ot->idname = "FONT_OT_move_select";
1546
1547 /* API callbacks. */
1548 ot->exec = move_select_exec;
1549 ot->poll = ED_operator_editfont;
1550
1551 /* flags */
1552 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1553
1554 /* properties */
1555 RNA_def_enum(ot->srna,
1556 "type",
1558 LINE_BEGIN,
1559 "Type",
1560 "Where to move cursor to, to make a selection");
1561}
1562
1564
1565/* -------------------------------------------------------------------- */
1568
1570{
1571 Object *obedit = CTX_data_edit_object(C);
1572 Curve *cu = static_cast<Curve *>(obedit->data);
1573 EditFont *ef = cu->editfont;
1574 float kern, delta = RNA_float_get(op->ptr, "delta");
1575 int selstart, selend;
1576 bool changed = false;
1577
1578 const bool has_select = BKE_vfont_select_get(cu, &selstart, &selend);
1579 if (has_select) {
1580 selstart -= 1;
1581 }
1582 else {
1583 selstart = selend = ef->pos - 1;
1584 }
1585 selstart = max_ii(0, selstart);
1586
1587 for (int i = selstart; i <= selend; i++) {
1588 kern = ef->textbufinfo[i].kern + delta;
1589
1590 if (ef->textbufinfo[i].kern != kern) {
1591 ef->textbufinfo[i].kern = kern;
1592 changed = true;
1593 }
1594 }
1595
1596 if (changed) {
1597 text_update_edited(C, obedit, FO_EDIT);
1598
1599 return OPERATOR_FINISHED;
1600 }
1601 return OPERATOR_CANCELLED;
1602}
1603
1605{
1606 /* identifiers */
1607 ot->name = "Change Spacing";
1608 ot->description = "Change font spacing";
1609 ot->idname = "FONT_OT_change_spacing";
1610
1611 /* API callbacks. */
1612 ot->exec = change_spacing_exec;
1613 ot->poll = ED_operator_editfont;
1614
1615 /* flags */
1616 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1617
1618 /* properties */
1619 RNA_def_float(ot->srna,
1620 "delta",
1621 1.0,
1622 0.0,
1623 0.0,
1624 "Delta",
1625 "Amount to decrease or increase character spacing with",
1626 0.0,
1627 0.0);
1628}
1629
1631
1632/* -------------------------------------------------------------------- */
1635
1637{
1638 Object *obedit = CTX_data_edit_object(C);
1639 Curve *cu = static_cast<Curve *>(obedit->data);
1640 EditFont *ef = cu->editfont;
1641 int character, delta = RNA_int_get(op->ptr, "delta");
1642
1643 if (ef->pos <= 0) {
1644 return OPERATOR_CANCELLED;
1645 }
1646
1647 character = ef->textbuf[ef->pos - 1];
1648 character += delta;
1649 CLAMP(character, 0, 255);
1650
1651 if (character == ef->textbuf[ef->pos - 1]) {
1652 return OPERATOR_CANCELLED;
1653 }
1654
1655 ef->textbuf[ef->pos - 1] = character;
1656
1657 text_update_edited(C, obedit, FO_EDIT);
1658
1659 return OPERATOR_FINISHED;
1660}
1661
1663{
1664 /* identifiers */
1665 ot->name = "Change Character";
1666 ot->description = "Change font character code";
1667 ot->idname = "FONT_OT_change_character";
1668
1669 /* API callbacks. */
1670 ot->exec = change_character_exec;
1671 ot->poll = ED_operator_editfont;
1672
1673 /* flags */
1674 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1675
1676 /* properties */
1677 RNA_def_int(ot->srna,
1678 "delta",
1679 1,
1680 -255,
1681 255,
1682 "Delta",
1683 "Number to increase or decrease character code with",
1684 -255,
1685 255);
1686}
1687
1689
1690/* -------------------------------------------------------------------- */
1693
1695{
1696 Object *obedit = CTX_data_edit_object(C);
1697 Curve *cu = static_cast<Curve *>(obedit->data);
1698 EditFont *ef = cu->editfont;
1699
1700 insert_into_textbuf(obedit, '\n');
1701
1702 ef->selstart = ef->selend = 0;
1703
1704 text_update_edited(C, obedit, FO_EDIT);
1705
1706 return OPERATOR_FINISHED;
1707}
1708
1710{
1711 /* identifiers */
1712 ot->name = "Line Break";
1713 ot->description = "Insert line break at cursor position";
1714 ot->idname = "FONT_OT_line_break";
1715
1716 /* API callbacks. */
1717 ot->exec = line_break_exec;
1718 ot->poll = ED_operator_editfont;
1719
1720 /* flags */
1721 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1722}
1723
1725
1726/* -------------------------------------------------------------------- */
1729
1731 {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
1732 {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
1733 {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
1734 {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
1735 {DEL_SELECTION, "SELECTION", 0, "Selection", ""},
1736 {DEL_NEXT_SEL, "NEXT_OR_SELECTION", 0, "Next or Selection", ""},
1737 {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", 0, "Previous or Selection", ""},
1738 {0, nullptr, 0, nullptr, nullptr},
1739};
1740
1742{
1743 Object *obedit = CTX_data_edit_object(C);
1744 Curve *cu = static_cast<Curve *>(obedit->data);
1745 EditFont *ef = cu->editfont;
1746 int selstart, selend, type = RNA_enum_get(op->ptr, "type");
1747 int range[2] = {0, 0};
1748 bool has_select = false;
1749
1750 if (ef->len == 0) {
1751 return OPERATOR_CANCELLED;
1752 }
1753
1754 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
1755 if (type == DEL_NEXT_SEL) {
1756 type = DEL_SELECTION;
1757 }
1758 else if (type == DEL_PREV_SEL) {
1759 type = DEL_SELECTION;
1760 }
1761 has_select = true;
1762 }
1763 else {
1764 if (type == DEL_NEXT_SEL) {
1765 type = DEL_NEXT_CHAR;
1766 }
1767 else if (type == DEL_PREV_SEL) {
1768 type = DEL_PREV_CHAR;
1769 }
1770 }
1771
1772 switch (type) {
1773 case DEL_SELECTION:
1774 if (!kill_selection(obedit, 0)) {
1775 return OPERATOR_CANCELLED;
1776 }
1777 break;
1778 case DEL_PREV_CHAR:
1779 if (ef->pos <= 0) {
1780 return OPERATOR_CANCELLED;
1781 }
1782
1783 range[1] = ef->pos;
1785 range[0] = ef->pos;
1786 break;
1787 case DEL_NEXT_CHAR:
1788 if (ef->pos >= ef->len) {
1789 return OPERATOR_CANCELLED;
1790 }
1791
1792 range[0] = ef->pos;
1793 range[1] = ef->pos;
1794 BLI_str_cursor_step_next_utf32(ef->textbuf, ef->len, &range[1]);
1795 break;
1796 case DEL_NEXT_WORD: {
1797 int pos = ef->pos;
1799 ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
1800 range[0] = ef->pos;
1801 range[1] = pos;
1802 break;
1803 }
1804
1805 case DEL_PREV_WORD: {
1806 int pos = ef->pos;
1808 ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
1809 range[0] = pos;
1810 range[1] = ef->pos;
1811 ef->pos = pos;
1812 break;
1813 }
1814 default:
1815 return OPERATOR_CANCELLED;
1816 }
1817
1818 if (range[0] != range[1]) {
1819 BLI_assert(range[0] < range[1]);
1820 int len_remove = range[1] - range[0];
1821 int len_tail = ef->len - range[1];
1822 if (has_select) {
1823 for (int i = 0; i < 2; i++) {
1824 int *sel = i ? &ef->selend : &ef->selstart;
1825 if (*sel <= range[0]) {
1826 /* pass */
1827 }
1828 else if (*sel >= range[1]) {
1829 *sel -= len_remove;
1830 }
1831 else {
1832 BLI_assert(*sel < range[1]);
1833 /* pass */
1834 *sel = range[0];
1835 }
1836 }
1837 }
1838
1839 memmove(&ef->textbuf[range[0]], &ef->textbuf[range[1]], sizeof(*ef->textbuf) * len_tail);
1840 memmove(&ef->textbufinfo[range[0]],
1841 &ef->textbufinfo[range[1]],
1842 sizeof(*ef->textbufinfo) * len_tail);
1843
1844 ef->len -= len_remove;
1845 ef->textbuf[ef->len] = '\0';
1846
1848 }
1849
1850 text_update_edited(C, obedit, FO_EDIT);
1851
1852 return OPERATOR_FINISHED;
1853}
1854
1856{
1857 /* identifiers */
1858 ot->name = "Delete";
1859 ot->description = "Delete text by cursor position";
1860 ot->idname = "FONT_OT_delete";
1861
1862 /* API callbacks. */
1863 ot->exec = delete_exec;
1864 ot->poll = ED_operator_editfont;
1865
1866 /* flags */
1867 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1868
1869 /* properties */
1870 RNA_def_enum(ot->srna,
1871 "type",
1874 "Type",
1875 "Which part of the text to delete");
1876}
1877
1879
1880/* -------------------------------------------------------------------- */
1883
1885{
1886 Object *obedit = CTX_data_edit_object(C);
1887 char *inserted_utf8;
1888 char32_t *inserted_text;
1889 int a, len;
1890
1891 if (!RNA_struct_property_is_set(op->ptr, "text")) {
1892 return OPERATOR_CANCELLED;
1893 }
1894
1895 inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", nullptr, 0, nullptr);
1896 len = BLI_strlen_utf8(inserted_utf8);
1897
1898 inserted_text = MEM_calloc_arrayN<char32_t>((len + 1), "FONT_insert_text");
1899 len = BLI_str_utf8_as_utf32(inserted_text, inserted_utf8, MAXTEXT);
1900
1901 for (a = 0; a < len; a++) {
1902 insert_into_textbuf(obedit, inserted_text[a]);
1903 }
1904
1905 MEM_freeN(inserted_text);
1906 MEM_freeN(inserted_utf8);
1907
1908 kill_selection(obedit, len);
1909 text_update_edited(C, obedit, FO_EDIT);
1910
1911 return OPERATOR_FINISHED;
1912}
1913
1915{
1916 Object *obedit = CTX_data_edit_object(C);
1917 Curve *cu = static_cast<Curve *>(obedit->data);
1918 EditFont *ef = cu->editfont;
1919 static bool accentcode = false;
1920 const bool alt = event->modifier & KM_ALT;
1921 const bool shift = event->modifier & KM_SHIFT;
1922 const bool ctrl = event->modifier & KM_CTRL;
1923 char32_t insert_char_override = 0;
1924 char32_t inserted_text[2] = {0};
1925
1926 if (RNA_struct_property_is_set(op->ptr, "text")) {
1927 return insert_text_exec(C, op);
1928 }
1929
1930 if (RNA_struct_property_is_set(op->ptr, "accent")) {
1931 if (ef->len != 0 && ef->pos > 0) {
1932 accentcode = true;
1933 }
1934 return OPERATOR_FINISHED;
1935 }
1936
1937 if (event->type == EVT_BACKSPACEKEY) {
1938 if (alt && ef->len != 0 && ef->pos > 0) {
1939 accentcode = true;
1940 }
1941 return OPERATOR_PASS_THROUGH;
1942 }
1943
1944 /* Tab typically exit edit-mode, but we allow it to be typed using modifier keys. */
1945 if (event->type == EVT_TABKEY) {
1946 if ((alt || ctrl || shift) == 0) {
1947 return OPERATOR_PASS_THROUGH;
1948 }
1949 insert_char_override = '\t';
1950 }
1951
1952 if (insert_char_override || event->utf8_buf[0]) {
1953 if (insert_char_override) {
1954 /* Handle case like TAB ('\t'). */
1955 inserted_text[0] = insert_char_override;
1956 insert_into_textbuf(obedit, insert_char_override);
1957 text_update_edited(C, obedit, FO_EDIT);
1958 }
1959 else {
1960 BLI_assert(event->utf8_buf[0]);
1961 if (accentcode) {
1962 if (ef->pos > 0) {
1963 inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1],
1965 ef->textbuf[ef->pos - 1] = inserted_text[0];
1966 }
1967 accentcode = false;
1968 }
1969 else if (event->utf8_buf[0]) {
1970 inserted_text[0] = BLI_str_utf8_as_unicode_or_error(event->utf8_buf);
1971 insert_into_textbuf(obedit, inserted_text[0]);
1972 accentcode = false;
1973 }
1974 else {
1975 BLI_assert(0);
1976 }
1977
1978 kill_selection(obedit, 1);
1979 text_update_edited(C, obedit, FO_EDIT);
1980 }
1981 }
1982 else {
1983 return OPERATOR_PASS_THROUGH;
1984 }
1985
1986 if (inserted_text[0]) {
1987 /* Store as UTF8 in RNA string. */
1988 char inserted_utf8[8] = {0};
1989
1990 BLI_str_utf32_as_utf8(inserted_utf8, inserted_text, sizeof(inserted_utf8));
1991 RNA_string_set(op->ptr, "text", inserted_utf8);
1992 }
1993
1994 return OPERATOR_FINISHED;
1995}
1996
1998{
1999 /* identifiers */
2000 ot->name = "Insert Text";
2001 ot->description = "Insert text at cursor position";
2002 ot->idname = "FONT_OT_text_insert";
2003
2004 /* API callbacks. */
2005 ot->exec = insert_text_exec;
2006 ot->invoke = insert_text_invoke;
2007 ot->poll = ED_operator_editfont;
2008
2009 /* flags */
2010 ot->flag = OPTYPE_UNDO;
2011
2012 /* properties */
2013 RNA_def_string(ot->srna, "text", nullptr, 0, "Text", "Text to insert at the cursor position");
2015 ot->srna,
2016 "accent",
2017 false,
2018 "Accent Mode",
2019 "Next typed character will strike through previous, for special character input");
2020}
2021
2023
2024/* -------------------------------------------------------------------- */
2027
2028static int font_cursor_text_index_from_event(bContext *C, Object *obedit, const wmEvent *event)
2029{
2030 /* Calculate a plane from the text object's orientation. */
2031 float plane[4];
2033 plane, obedit->object_to_world().location(), obedit->object_to_world().ptr()[2]);
2034
2035 /* Convert Mouse location in region to 3D location in world space. */
2036 float mal_fl[2] = {float(event->mval[0]), float(event->mval[1])};
2037 float mouse_loc[3];
2038 ED_view3d_win_to_3d_on_plane(CTX_wm_region(C), plane, mal_fl, true, mouse_loc);
2039
2040 /* Convert to object space and scale by font size. */
2041 mul_m4_v3(obedit->world_to_object().ptr(), mouse_loc);
2042
2043 float curs_loc[2] = {mouse_loc[0], mouse_loc[1]};
2044 return BKE_vfont_cursor_to_text_index(obedit, curs_loc);
2045}
2046
2047static void font_cursor_set_apply(bContext *C, const wmEvent *event)
2048{
2051 Curve *cu = static_cast<Curve *>(ob->data);
2052 EditFont *ef = cu->editfont;
2053 BLI_assert(ef->len >= 0);
2054
2055 const int string_offset = font_cursor_text_index_from_event(C, ob, event);
2056
2057 if (string_offset > ef->len || string_offset < 0) {
2058 return;
2059 }
2060
2061 cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
2062
2064
2065 if (!ef->selboxes && (ef->selstart == 0)) {
2066 if (ef->pos == 0) {
2067 ef->selstart = ef->selend = 1;
2068 }
2069 else {
2070 ef->selstart = ef->selend = string_offset + 1;
2071 }
2072 }
2073 ef->selend = string_offset;
2074 ef->pos = string_offset;
2075
2076 DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SELECT);
2078}
2079
2081 wmOperator *op,
2082 const wmEvent *event)
2083{
2084 Object *obedit = CTX_data_active_object(C);
2085 Curve *cu = static_cast<Curve *>(obedit->data);
2086 EditFont *ef = cu->editfont;
2087
2088 font_cursor_set_apply(C, event);
2089 ef->selstart = 0;
2090 ef->selend = 0;
2092
2094}
2095
2097 wmOperator * /*op*/,
2098 const wmEvent *event)
2099{
2100 switch (event->type) {
2101 case LEFTMOUSE:
2102 if (event->val == KM_RELEASE) {
2103 font_cursor_set_apply(C, event);
2104 return OPERATOR_FINISHED;
2105 }
2106 break;
2107 case MIDDLEMOUSE:
2108 case RIGHTMOUSE:
2109 return OPERATOR_FINISHED;
2110 case MOUSEMOVE:
2111 font_cursor_set_apply(C, event);
2112 break;
2113 default: {
2114 break;
2115 }
2116 }
2118}
2119
2121{
2122 /* identifiers */
2123 ot->name = "Set Selection";
2124 ot->idname = "FONT_OT_selection_set";
2125 ot->description = "Set cursor selection";
2126
2127 /* API callbacks. */
2128 ot->invoke = font_selection_set_invoke;
2130 ot->poll = ED_operator_editfont;
2131}
2132
2134
2135/* -------------------------------------------------------------------- */
2138
2140{
2141 Object *obedit = CTX_data_edit_object(C);
2142 Curve *cu = static_cast<Curve *>(obedit->data);
2143 EditFont *ef = cu->editfont;
2144
2146 ef->pos = ef->selend;
2147
2148 /* XXX: Text object selection start is 1-based, unlike text processing elsewhere in Blender. */
2149 ef->selstart += 1;
2150
2152 text_update_edited(C, obedit, FO_CURS);
2153
2154 return OPERATOR_FINISHED;
2155}
2156
2158{
2159 /* identifiers */
2160 ot->name = "Select Word";
2161 ot->idname = "FONT_OT_select_word";
2162 ot->description = "Select word under cursor";
2163
2164 /* API callbacks. */
2165 ot->exec = font_select_word_exec;
2166 ot->poll = ED_operator_editfont;
2167}
2168
2170
2171/* -------------------------------------------------------------------- */
2174
2176{
2177 Object *obedit = CTX_data_active_object(C);
2178 Curve *cu = static_cast<Curve *>(obedit->data);
2179 int i;
2180
2181 if (cu->totbox < 256) {
2182 for (i = cu->totbox; i > cu->actbox; i--) {
2183 cu->tb[i] = cu->tb[i - 1];
2184 }
2185 cu->tb[cu->actbox] = cu->tb[cu->actbox - 1];
2186 cu->actbox++;
2187 cu->totbox++;
2188 }
2189
2190 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
2192 return OPERATOR_FINISHED;
2193}
2194
2196{
2197 /* identifiers */
2198 ot->name = "Add Text Box";
2199 ot->description = "Add a new text box";
2200 ot->idname = "FONT_OT_textbox_add";
2201
2202 /* API callbacks. */
2203 ot->exec = textbox_add_exec;
2205
2206 /* flags */
2207 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2208}
2209
2211
2212/* -------------------------------------------------------------------- */
2215
2217{
2218 Object *obedit = CTX_data_active_object(C);
2219 Curve *cu = static_cast<Curve *>(obedit->data);
2220 int i;
2221 int index = RNA_int_get(op->ptr, "index");
2222
2223 if (cu->totbox > 1) {
2224 for (i = index; i < cu->totbox; i++) {
2225 cu->tb[i] = cu->tb[i + 1];
2226 }
2227 cu->totbox--;
2228 if (cu->actbox >= index) {
2229 cu->actbox--;
2230 }
2231 }
2232
2233 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
2235
2236 return OPERATOR_FINISHED;
2237}
2238
2240{
2241 /* identifiers */
2242 ot->name = "Remove Text Box";
2243 ot->description = "Remove the text box";
2244 ot->idname = "FONT_OT_textbox_remove";
2245
2246 /* API callbacks. */
2247 ot->exec = textbox_remove_exec;
2249
2250 /* flags */
2251 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2252
2253 RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX);
2254}
2255
2257
2258/* -------------------------------------------------------------------- */
2261
2263{
2264 Curve *cu = static_cast<Curve *>(obedit->data);
2265 EditFont *ef = cu->editfont;
2266
2267 if (ef == nullptr) {
2268 ef = cu->editfont = MEM_callocN<EditFont>("editfont");
2269
2270 ef->textbuf = static_cast<char32_t *>(
2271 MEM_callocN((MAXTEXT + 4) * sizeof(*ef->textbuf), "texteditbuf"));
2272 ef->textbufinfo = MEM_calloc_arrayN<CharInfo>((MAXTEXT + 4), "texteditbufinfo");
2273 }
2274
2275 /* Convert the original text to chat32_t. */
2276 if (cu->str) {
2277 int len_char32 = BLI_str_utf8_as_utf32(ef->textbuf, cu->str, MAXTEXT + 4);
2278 BLI_assert(len_char32 == cu->len_char32);
2279 ef->len = len_char32;
2280 BLI_assert(ef->len >= 0);
2281 }
2282
2283 /* Old files may not have this initialized (v2.34). Leaving zeroed is OK. */
2284 if (cu->strinfo) {
2285 memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
2286 }
2287
2288 ef->pos = cu->pos;
2289 ef->pos = std::min(ef->pos, ef->len);
2290
2291 cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
2292
2293 /* Other vars */
2294 ef->selstart = cu->selstart;
2295 ef->selend = cu->selend;
2296
2297 /* text may have been modified by Python */
2299}
2300
2302{
2303 Curve *cu = static_cast<Curve *>(obedit->data);
2304 EditFont *ef = cu->editfont;
2305
2306 /* Free the old curve string */
2307 if (cu->str) {
2308 MEM_freeN(cu->str);
2309 }
2310
2311 /* Calculate the actual string length in UTF8 variable characters. */
2312 cu->len_char32 = ef->len;
2314
2315 /* Alloc memory for UTF8 variable char length string. */
2316 cu->str = MEM_malloc_arrayN<char>(cu->len + sizeof(char32_t), "str");
2317
2318 /* Copy the wchar to UTF8. */
2319 BLI_str_utf32_as_utf8(cu->str, ef->textbuf, cu->len + 1);
2320
2321 if (cu->strinfo) {
2322 MEM_freeN(cu->strinfo);
2323 }
2324 cu->strinfo = MEM_calloc_arrayN<CharInfo>((cu->len_char32 + 4), "texteditinfo");
2325 memcpy(cu->strinfo, ef->textbufinfo, cu->len_char32 * sizeof(CharInfo));
2326
2327 /* Other vars */
2328 cu->pos = ef->pos;
2329 cu->selstart = ef->selstart;
2330 cu->selend = ef->selend;
2331}
2332
2334{
2336}
2337
2339
2340/* -------------------------------------------------------------------- */
2343
2345 {CASE_LOWER, "LOWER", 0, "Lower", ""},
2346 {CASE_UPPER, "UPPER", 0, "Upper", ""},
2347 {0, nullptr, 0, nullptr, nullptr},
2348};
2349
2351{
2352 Object *obedit = CTX_data_edit_object(C);
2353 Curve *cu = static_cast<Curve *>(obedit->data);
2354 int selstart, selend;
2355
2356 if (BKE_vfont_select_get(cu, &selstart, &selend)) {
2357 EditFont *ef = cu->editfont;
2358 char32_t *str = &ef->textbuf[selstart];
2359
2360 for (int len = (selend - selstart) + 1; len; len--, str++) {
2361 *str = (ccase == CASE_LOWER) ? BLI_str_utf32_char_to_lower(*str) :
2363 }
2364
2365 text_update_edited(C, obedit, FO_EDIT);
2366 }
2367
2368 return OPERATOR_FINISHED;
2369}
2370
2372{
2373 return set_case(C, RNA_enum_get(op->ptr, "case"));
2374}
2375
2377{
2378 PropertyRNA *prop;
2379
2380 /* identifiers */
2381 ot->name = "Set Case";
2382 ot->description = "Set font case";
2383 ot->idname = "FONT_OT_case_set";
2384
2385 /* API callbacks. */
2386 ot->exec = set_case_exec;
2387 ot->poll = ED_operator_editfont;
2388
2389 /* flags */
2390 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2391
2392 /* properties */
2393 prop = RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case");
2395}
2396
2398
2399/* -------------------------------------------------------------------- */
2402
2404{
2405 Object *obedit = CTX_data_edit_object(C);
2406 Curve *cu = static_cast<Curve *>(obedit->data);
2407 EditFont *ef = cu->editfont;
2408 int ccase = CASE_UPPER;
2409
2410 const char32_t *str = ef->textbuf;
2411 while (*str) {
2412 if (*str >= 'a' && *str <= 'z') {
2413 ccase = CASE_LOWER;
2414 break;
2415 }
2416
2417 str++;
2418 }
2419
2420 return set_case(C, ccase);
2421}
2422
2424{
2425 /* identifiers */
2426 ot->name = "Toggle Case";
2427 ot->description = "Toggle font case";
2428 ot->idname = "FONT_OT_case_toggle";
2429
2430 /* API callbacks. */
2431 ot->exec = toggle_case_exec;
2432 ot->poll = ED_operator_editfont;
2433
2434 /* flags */
2435 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2436}
2437
2438/* **************** Open Font ************** */
2439
2441{
2442 PropertyPointerRNA *pprop;
2443
2444 op->customdata = pprop = MEM_new<PropertyPointerRNA>("OpenPropertyPointerRNA");
2446}
2447
2448static void font_open_cancel(bContext * /*C*/, wmOperator *op)
2449{
2450 MEM_delete(static_cast<PropertyPointerRNA *>(op->customdata));
2451 op->customdata = nullptr;
2452}
2453
2455{
2456 Main *bmain = CTX_data_main(C);
2457 VFont *font;
2458 PropertyPointerRNA *pprop;
2459 char filepath[FILE_MAX];
2460 RNA_string_get(op->ptr, "filepath", filepath);
2461
2462 font = BKE_vfont_load(bmain, filepath);
2463
2464 if (!font) {
2465 if (op->customdata) {
2466 MEM_delete(static_cast<PropertyPointerRNA *>(op->customdata));
2467 }
2468 return OPERATOR_CANCELLED;
2469 }
2470
2471 if (!op->customdata) {
2473 }
2474
2475 /* hook into UI */
2476 pprop = static_cast<PropertyPointerRNA *>(op->customdata);
2477
2478 if (pprop->prop) {
2479 /* when creating new ID blocks, use is already 1, but RNA
2480 * pointer use also increases user, so this compensates it */
2481 id_us_min(&font->id);
2482
2483 PointerRNA idptr = RNA_id_pointer_create(&font->id);
2484 RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, nullptr);
2485 RNA_property_update(C, &pprop->ptr, pprop->prop);
2486 }
2487
2488 MEM_delete(static_cast<PropertyPointerRNA *>(op->customdata));
2489
2490 return OPERATOR_FINISHED;
2491}
2492
2494{
2495 VFont *vfont = nullptr;
2496 char filepath[FILE_MAX];
2497
2498 PointerRNA idptr;
2499 PropertyPointerRNA *pprop;
2500
2502
2503 /* hook into UI */
2504 pprop = static_cast<PropertyPointerRNA *>(op->customdata);
2505
2506 if (pprop->prop) {
2507 idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop);
2508 vfont = (VFont *)idptr.owner_id;
2509 }
2510
2511 PropertyRNA *prop_filepath = RNA_struct_find_property(op->ptr, "filepath");
2512 if (RNA_property_is_set(op->ptr, prop_filepath)) {
2513 return font_open_exec(C, op);
2514 }
2515
2516 if (vfont && !BKE_vfont_is_builtin(vfont)) {
2517 STRNCPY(filepath, vfont->filepath);
2518 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
2519 }
2520 else {
2521 STRNCPY(filepath, U.fontdir);
2522 BLI_path_slash_ensure(filepath, sizeof(filepath));
2523 /* The file selector will expand the blend-file relative prefix. */
2524 }
2525 RNA_property_string_set(op->ptr, prop_filepath, filepath);
2526
2528
2530}
2531
2533{
2534 /* identifiers */
2535 ot->name = "Open Font";
2536 ot->idname = "FONT_OT_open";
2537 ot->description = "Load a new font from a file";
2538
2539 /* API callbacks. */
2540 ot->exec = font_open_exec;
2541 ot->invoke = open_invoke;
2542 ot->cancel = font_open_cancel;
2543
2544 /* flags */
2545 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2546
2547 /* properties */
2555}
2556
2558
2559/* -------------------------------------------------------------------- */
2562
2564{
2565 VFont *builtin_font;
2566
2567 PropertyPointerRNA pprop;
2568
2570
2571 if (pprop.prop == nullptr) {
2572 BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink");
2573 return OPERATOR_CANCELLED;
2574 }
2575
2576 builtin_font = BKE_vfont_builtin_ensure();
2577
2578 PointerRNA idptr = RNA_id_pointer_create(&builtin_font->id);
2579 RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, nullptr);
2580 RNA_property_update(C, &pprop.ptr, pprop.prop);
2581
2582 return OPERATOR_FINISHED;
2583}
2584
2586{
2587 /* identifiers */
2588 ot->name = "Unlink";
2589 ot->idname = "FONT_OT_unlink";
2590 ot->description = "Unlink active font data-block";
2591
2592 /* API callbacks. */
2593 ot->exec = font_unlink_exec;
2594}
2595
2597 bContext *C,
2598 const int mval[2],
2599 /* NOTE: `params->deselect_all` is ignored as only one text-box is active at once. */
2601{
2603 Object *obedit = CTX_data_edit_object(C);
2604 Curve *cu = static_cast<Curve *>(obedit->data);
2605 /* bias against the active, in pixels, allows cycling */
2606 const float active_bias_px = 4.0f;
2607 const float mval_fl[2] = {float(mval[0]), float(mval[1])};
2608 const int i_actbox = max_ii(0, cu->actbox - 1);
2609 int i_iter, actbox_select = -1;
2610 const float dist = ED_view3d_select_dist_px();
2611 float dist_sq_best = dist * dist;
2612
2614
2616
2617 /* currently only select active */
2618 (void)params;
2619
2620 for (i_iter = 0; i_iter < cu->totbox; i_iter++) {
2621 int i = (i_iter + i_actbox) % cu->totbox;
2622 float dist_sq_min;
2623 int j, j_prev;
2624
2625 float obedit_co[4][3];
2626 float screen_co[4][2];
2627 rctf rect;
2628 int project_ok = 0;
2629
2630 BKE_curve_rect_from_textbox(cu, &cu->tb[i], &rect);
2631
2632 copy_v3_fl3(obedit_co[0], rect.xmin, rect.ymin, 0.0f);
2633 copy_v3_fl3(obedit_co[1], rect.xmin, rect.ymax, 0.0f);
2634 copy_v3_fl3(obedit_co[2], rect.xmax, rect.ymax, 0.0f);
2635 copy_v3_fl3(obedit_co[3], rect.xmax, rect.ymin, 0.0f);
2636
2637 for (j = 0; j < 4; j++) {
2639 vc.region, obedit_co[j], screen_co[j], V3D_PROJ_TEST_CLIP_BB) == V3D_PROJ_RET_OK)
2640 {
2641 project_ok |= (1 << j);
2642 }
2643 }
2644
2645 dist_sq_min = dist_sq_best;
2646 for (j = 0, j_prev = 3; j < 4; j_prev = j++) {
2647 if ((project_ok & (1 << j)) && (project_ok & (1 << j_prev))) {
2648 const float dist_test_sq = dist_squared_to_line_segment_v2(
2649 mval_fl, screen_co[j_prev], screen_co[j]);
2650 dist_sq_min = std::min(dist_sq_min, dist_test_sq);
2651 }
2652 }
2653
2654 /* Bias in pixels to cycle selection. */
2655 if (i_iter == 0) {
2656 dist_sq_min += active_bias_px;
2657 }
2658
2659 if (dist_sq_min < dist_sq_best) {
2660 dist_sq_best = dist_sq_min;
2661 actbox_select = i + 1;
2662 }
2663 }
2664
2665 if (actbox_select != -1) {
2666 if (cu->actbox != actbox_select) {
2667 cu->actbox = actbox_select;
2669 /* TODO: support #ID_RECALC_SELECT. */
2670 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_SYNC_TO_EVAL);
2671 }
2672 return true;
2673 }
2674 return false;
2675}
2676
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_curve_editfont_free(Curve *cu)
Definition curve.cc:320
void BKE_curve_rect_from_textbox(const Curve *cu, const TextBox *tb, rctf *r_rect)
Definition curve.cc:5432
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void id_us_plus(ID *id)
Definition lib_id.cc:353
void id_us_min(ID *id)
Definition lib_id.cc:361
General operations, lookup, etc. for blender objects.
Object * BKE_object_add(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
int BKE_vfont_select_get(const Curve *cu, int *r_start, int *r_end)
Definition vfont.cc:404
eEditFontMode
Definition BKE_vfont.hh:76
@ FO_PAGEUP
Definition BKE_vfont.hh:82
@ FO_EDIT
Definition BKE_vfont.hh:77
@ FO_CURSUP
Definition BKE_vfont.hh:79
@ FO_LINE_END
Definition BKE_vfont.hh:85
@ FO_LINE_BEGIN
Definition BKE_vfont.hh:84
@ FO_SELCHANGE
Definition BKE_vfont.hh:86
@ FO_CURS
Definition BKE_vfont.hh:78
@ FO_CURSDOWN
Definition BKE_vfont.hh:80
@ FO_PAGEDOWN
Definition BKE_vfont.hh:83
void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, size_t len)
Definition vfont.cc:475
#define FO_CURS_IS_MOTION(mode)
Definition BKE_vfont.hh:90
VFont * BKE_vfont_load(Main *bmain, const char *filepath)
Definition vfont.cc:299
bool BKE_vfont_is_builtin(const VFont *vfont)
Definition vfont.cc:273
void BKE_vfont_select_clamp(Curve *cu)
Definition vfont.cc:443
void BKE_vfont_clipboard_get(char32_t **r_text_buf, CharInfo **r_info_buf, size_t *r_len_utf8, size_t *r_len_utf32)
Definition vfont.cc:505
VFont * BKE_vfont_builtin_ensure()
Definition vfont.cc:382
bool BKE_vfont_to_curve(Object *ob, eEditFontMode mode)
int BKE_vfont_cursor_to_text_index(Object *ob, const float cursor_location[2])
void BKE_vfont_clipboard_free()
Definition vfont.cc:467
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
void * BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size)
Definition storage.cc:524
#define LISTBASE_FOREACH(type, var, list)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE int max_ii(int a, int b)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:217
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
Definition math_geom.cc:291
void mul_m4_v3(const float M[4][4], float r[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE void add_v3_v3(float r[3], const float a[3])
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
bool BLI_str_cursor_step_prev_utf32(const char32_t *str, int str_maxlen, int *pos)
void BLI_str_cursor_step_utf32(const char32_t *str, int str_maxlen, int *pos, eStrCursorJumpDirection direction, eStrCursorJumpType jump, bool use_init_step)
@ STRCUR_DIR_NEXT
@ STRCUR_DIR_PREV
void BLI_str_cursor_step_bounds_utf32(const char32_t *str, int str_maxlen, int pos, int *r_start, int *r_end)
bool BLI_str_cursor_step_next_utf32(const char32_t *str, int str_maxlen, int *pos)
@ STRCUR_JUMP_DELIM
size_t size_t size_t BLI_str_utf32_as_utf8_len_ex(const char32_t *src, size_t src_maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_str_utf32_as_utf8_len(const char32_t *src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char32_t BLI_str_utf32_char_to_lower(char32_t wc)
size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
size_t size_t BLI_str_utf32_as_utf8(char *__restrict dst, const char32_t *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char32_t BLI_str_utf32_char_to_upper(char32_t wc)
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w, const char *__restrict src_c, size_t dst_w_maxncpy) ATTR_NONNULL(1
unsigned int BLI_str_utf8_as_unicode_or_error(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONNULL(1
unsigned int uint
#define CLAMP(a, b, c)
#define CLAMP_MAX(a, c)
#define STREQ(a, b)
#define BLT_I18NCONTEXT_ID_TEXT
#define RPT_(msgid)
#define TIP_(msgid)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1009
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ CU_CHINFO_UNDERLINE
@ CU_CHINFO_BOLD
@ CU_CHINFO_ITALIC
@ CU_CHINFO_SMALLCAPS
Object is a sort of wrapper for general info.
@ OB_FONT
@ FILE_SORT_DEFAULT
@ FILE_SORT_ALPHA
@ FILE_SPECIAL
@ FILE_TYPE_TEXT
@ FILE_TYPE_FOLDER
@ FILE_TYPE_FTFONT
@ FILE_IMGDISPLAY
@ FILE_DEFAULTDISPLAY
#define UI_SCALE_FAC
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_outliner_select_sync_from_object_tag(bContext *C)
bool ED_operator_object_active_editable_font(bContext *C)
bool ED_operator_editfont(bContext *C)
float ED_view3d_select_dist_px()
@ V3D_PROJ_TEST_CLIP_BB
Definition ED_view3d.hh:280
eV3DProjStatus ED_view3d_project_float_object(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
void ED_view3d_init_mats_rv3d(const Object *ob, RegionView3D *rv3d)
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:256
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
bool ED_view3d_win_to_3d_on_plane(const ARegion *region, const float plane[4], const float mval[2], bool do_clip, float r_out[3])
static void split(const char *text, const char *seps, char ***str, int *count)
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
#define C
Definition RandGen.cpp:29
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
#define UI_UNIT_Y
uiBut * uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_block_theme_style_set(uiBlock *block, char theme_style)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
void UI_block_bounds_set_popup(uiBlock *block, int addval, const int bounds_offset[2])
Definition interface.cc:641
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
const uiStyle * UI_style_get_dpi()
void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free, bool can_refresh)
void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
@ UI_BLOCK_THEME_STYLE_POPUP
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
void UI_but_drawflag_disable(uiBut *but, int flag)
@ UI_BUT_TEXT_LEFT
void UI_context_active_but_prop_get_templateID(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop)
void UI_block_flag_enable(uiBlock *block, int flag)
@ UI_BTYPE_BUT
@ UI_BTYPE_TEXT
@ UI_BUT_ACTIVE_DEFAULT
@ UI_BUT_ACTIVATE_ON_INIT
@ UI_BLOCK_NUMSELECT
@ UI_BLOCK_KEEP_OPEN
@ UI_BLOCK_NO_WIN_CLIP
void UI_but_flag_enable(uiBut *but, int flag)
@ UI_LAYOUT_VERTICAL
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
@ UI_LAYOUT_PANEL
int uiLayoutGetWidth(uiLayout *layout)
uiBut * uiItemL_ex(uiLayout *layout, blender::StringRef name, int icon, bool highlight, bool redalert)
@ WM_FILESEL_RELPATH
Definition WM_api.hh:1072
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1075
@ WM_CAPABILITY_PRIMARY_CLIPBOARD
Definition WM_api.hh:187
@ FILE_OPENFILE
Definition WM_api.hh:1084
#define NC_GEOM
Definition WM_types.hh:390
@ KM_CTRL
Definition WM_types.hh:276
@ KM_ALT
Definition WM_types.hh:277
@ KM_SHIFT
Definition WM_types.hh:275
#define ND_DATA
Definition WM_types.hh:506
@ KM_RELEASE
Definition WM_types.hh:309
#define NA_ADDED
Definition WM_types.hh:583
ReportList * reports
Definition WM_types.hh:1025
#define NC_OBJECT
Definition WM_types.hh:376
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define U
#define NEXT_CHAR(fmt)
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
@ NEXT_LINE
@ TEXT_BEGIN
@ TEXT_END
@ LINE_BEGIN
@ PREV_WORD
@ PREV_LINE
@ PREV_CHAR
@ LINE_END
@ PREV_PAGE
@ NEXT_PAGE
@ NEXT_WORD
@ DEL_SELECTION
@ DEL_PREV_WORD
@ DEL_PREV_SEL
@ DEL_PREV_CHAR
@ DEL_NEXT_WORD
@ DEL_NEXT_CHAR
@ DEL_NEXT_SEL
@ CASE_LOWER
@ CASE_UPPER
static uiBlock * wm_block_insert_unicode_create(bContext *C, ARegion *region, void *arg_string)
Definition editfont.cc:699
void FONT_OT_textbox_add(wmOperatorType *ot)
Definition editfont.cc:2195
static void font_open_cancel(bContext *, wmOperator *op)
Definition editfont.cc:2448
static wmOperatorStatus set_style_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1004
void FONT_OT_style_toggle(wmOperatorType *ot)
Definition editfont.cc:1053
void ED_text_to_object(bContext *C, const Text *text, const bool split_lines)
Definition editfont.cc:916
static wmOperatorStatus set_style(bContext *C, const int style, const bool clear)
Definition editfont.cc:978
void FONT_OT_text_copy(wmOperatorType *ot)
Definition editfont.cc:1153
static wmOperatorStatus font_select_all_exec(bContext *C, wmOperator *)
Definition editfont.cc:1078
void FONT_OT_line_break(wmOperatorType *ot)
Definition editfont.cc:1709
void FONT_OT_select_word(wmOperatorType *ot)
Definition editfont.cc:2157
static void copy_selection(Object *obedit)
Definition editfont.cc:1118
void FONT_OT_unlink(wmOperatorType *ot)
Definition editfont.cc:2585
static wmOperatorStatus delete_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1741
static void font_select_update_primary_clipboard(Object *obedit)
Definition editfont.cc:460
static int kill_selection(Object *obedit, int ins)
Definition editfont.cc:432
static void text_insert_unicode_confirm(bContext *C, void *arg_block, void *arg_string)
Definition editfont.cc:672
static wmOperatorStatus line_break_exec(bContext *C, wmOperator *)
Definition editfont.cc:1694
void ED_curve_editfont_make(Object *obedit)
Definition editfont.cc:2262
void FONT_OT_select_all(wmOperatorType *ot)
Definition editfont.cc:1097
void FONT_OT_move(wmOperatorType *ot)
Definition editfont.cc:1509
static bool font_paste_wchar(Object *obedit, const char32_t *str, const size_t str_len, const CharInfo *str_info)
Definition editfont.cc:483
bool ED_curve_editfont_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params)
Definition editfont.cc:2596
static int font_cursor_text_index_from_event(bContext *C, Object *obedit, const wmEvent *event)
Definition editfont.cc:2028
static wmOperatorStatus change_spacing_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1569
static wmOperatorStatus paste_from_file_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition editfont.cc:622
#define MAXTEXT
Definition editfont.cc:68
static wmOperatorStatus change_character_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1636
void FONT_OT_text_cut(wmOperatorType *ot)
Definition editfont.cc:1189
static wmOperatorStatus cut_text_exec(bContext *C, wmOperator *)
Definition editfont.cc:1171
static wmOperatorStatus insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition editfont.cc:1914
void FONT_OT_change_spacing(wmOperatorType *ot)
Definition editfont.cc:1604
static wmOperatorStatus font_open_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2454
static void txt_add_object(bContext *C, const TextLine *firstline, int totline, const float offset[3])
Definition editfont.cc:838
void FONT_OT_text_insert_unicode(wmOperatorType *ot)
Definition editfont.cc:817
void ED_curve_editfont_load(Object *obedit)
Definition editfont.cc:2301
static wmOperatorStatus paste_from_file_exec(bContext *C, wmOperator *op)
Definition editfont.cc:610
void FONT_OT_change_character(wmOperatorType *ot)
Definition editfont.cc:1662
static const EnumPropertyItem style_items[]
Definition editfont.cc:970
void FONT_OT_delete(wmOperatorType *ot)
Definition editfont.cc:1855
void FONT_OT_textbox_remove(wmOperatorType *ot)
Definition editfont.cc:2239
static wmOperatorStatus paste_from_file(bContext *C, ReportList *reports, const char *filepath)
Definition editfont.cc:582
static wmOperatorStatus font_select_word_exec(bContext *C, wmOperator *)
Definition editfont.cc:2139
static wmOperatorStatus text_insert_unicode_invoke(bContext *C, wmOperator *, const wmEvent *)
Definition editfont.cc:807
static wmOperatorStatus set_case_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2371
static bool paste_selection(Object *obedit, ReportList *reports)
Definition editfont.cc:1210
static const EnumPropertyItem delete_type_items[]
Definition editfont.cc:1730
static void text_insert_unicode_cancel(bContext *C, void *arg_block, void *)
Definition editfont.cc:666
static wmOperatorStatus textbox_remove_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2216
void FONT_OT_open(wmOperatorType *ot)
Definition editfont.cc:2532
static wmOperatorStatus move_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1502
static wmOperatorStatus font_selection_set_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition editfont.cc:2080
void FONT_OT_text_paste_from_file(wmOperatorType *ot)
Definition editfont.cc:635
static wmOperatorStatus toggle_case_exec(bContext *C, wmOperator *)
Definition editfont.cc:2403
static char32_t findaccent(char32_t char1, const char code)
Definition editfont.cc:77
void FONT_OT_move_select(wmOperatorType *ot)
Definition editfont.cc:1540
static const EnumPropertyItem case_items[]
Definition editfont.cc:2344
static void text_update_edited(bContext *C, Object *obedit, const eEditFontMode mode)
Definition editfont.cc:405
static wmOperatorStatus set_case(bContext *C, int ccase)
Definition editfont.cc:2350
static wmOperatorStatus insert_text_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1884
static void font_cursor_set_apply(bContext *C, const wmEvent *event)
Definition editfont.cc:2047
static wmOperatorStatus copy_text_exec(bContext *C, wmOperator *)
Definition editfont.cc:1144
void FONT_OT_case_set(wmOperatorType *ot)
Definition editfont.cc:2376
static bool move_cursor_drop_select(Object *obedit, int dir)
Definition editfont.cc:1346
void FONT_OT_case_toggle(wmOperatorType *ot)
Definition editfont.cc:2423
void ED_curve_editfont_free(Object *obedit)
Definition editfont.cc:2333
static void font_ui_template_init(bContext *C, wmOperator *op)
Definition editfont.cc:2440
static wmOperatorStatus toggle_style_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1038
static char * font_select_to_buffer(Object *obedit)
Definition editfont.cc:559
void FONT_OT_selection_set(wmOperatorType *ot)
Definition editfont.cc:2120
void FONT_OT_text_paste(wmOperatorType *ot)
Definition editfont.cc:1295
static int insert_into_textbuf(Object *obedit, uintptr_t c)
Definition editfont.cc:377
static wmOperatorStatus paste_text_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1226
static wmOperatorStatus move_select_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1533
static wmOperatorStatus move_cursor(bContext *C, int type, const bool select)
Definition editfont.cc:1369
void FONT_OT_text_insert(wmOperatorType *ot)
Definition editfont.cc:1997
static wmOperatorStatus font_unlink_exec(bContext *C, wmOperator *op)
Definition editfont.cc:2563
static wmOperatorStatus open_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition editfont.cc:2493
static wmOperatorStatus font_selection_set_modal(bContext *C, wmOperator *, const wmEvent *event)
Definition editfont.cc:2096
void FONT_OT_style_set(wmOperatorType *ot)
Definition editfont.cc:1012
static const EnumPropertyItem move_type_items[]
Definition editfont.cc:1325
static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
Definition editfont.cc:535
static wmOperatorStatus textbox_add_exec(bContext *C, wmOperator *)
Definition editfont.cc:2175
#define rot(x, k)
#define str(s)
uint pos
#define select(A, B, C)
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
static void clear(Message &msg)
Definition msgfmt.cc:213
bool material_active_index_set(Object *ob, int index)
void init_transform_on_add(Object *object, const float loc[3], const float rot[3])
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_int_get(PointerRNA *ptr, const char *name)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
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_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
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_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
struct VFont * vfont
struct CharInfo curinfo
struct TextBox * tb
struct EditFont * editfont
struct CharInfo * strinfo
char * str
CharInfo * textbufinfo
Definition BKE_vfont.hh:42
int selend
Definition BKE_vfont.hh:60
EditFontSelBox * selboxes
Definition BKE_vfont.hh:49
char32_t * textbuf
Definition BKE_vfont.hh:40
int selstart
Definition BKE_vfont.hh:60
Definition DNA_ID.h:404
void * first
float loc[3]
ID * owner_id
Definition RNA_types.hh:51
PropertyRNA * prop
Definition RNA_types.hh:134
float viewinv[4][4]
char * line
struct TextLine * next
ListBase lines
char filepath[1024]
RegionView3D * rv3d
Definition ED_view3d.hh:80
ARegion * region
Definition ED_view3d.hh:77
Object * obedit
Definition ED_view3d.hh:76
float xmax
float xmin
float ymax
float ymin
void label(blender::StringRef name, int icon)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiLayout & split(float percentage, bool align)
wmEventType type
Definition WM_types.hh:754
short val
Definition WM_types.hh:756
char utf8_buf[6]
Definition WM_types.hh:768
int mval[2]
Definition WM_types.hh:760
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
uint len
size_t len_utf8
Definition vfont.cc:464
void WM_event_add_fileselect(bContext *C, wmOperator *op)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ EVT_TABKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ MIDDLEMOUSE
@ EVT_BACKSPACEKEY
wmOperatorType * ot
Definition wm_files.cc:4226
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
void WM_clipboard_text_set(const char *buf, bool selection)
char * WM_clipboard_text_get(bool selection, bool ensure_utf8, int *r_len)
eWM_CapabilitiesFlag WM_capabilities_flag()