@@ -396,8 +396,215 @@ bool ScriptTextEditor::show_members_overview() {
396
396
return true ;
397
397
}
398
398
399
+ bool ScriptTextEditor::_is_valid_color_info (const Array &p_info) {
400
+ if (p_info.size () < INFO_COLOR_MAX) {
401
+ return false ;
402
+ }
403
+ if (p_info[INFO_COLOR].get_type () != Variant::COLOR) {
404
+ return false ;
405
+ }
406
+ if (!p_info[INFO_COLOR_END].is_num () || !p_info[INFO_COLOR_MODE].is_num ()) {
407
+ return false ;
408
+ }
409
+ return true ;
410
+ }
411
+
412
+ Array ScriptTextEditor::_inline_object_parse (const String &p_text, int p_line) {
413
+ Array result;
414
+ int i_end_previous = 0 ;
415
+ int i_start = p_text.find (" Color" );
416
+
417
+ while (i_start != -1 ) {
418
+ int i_par_start = p_text.find_char (' (' , i_start + 5 );
419
+ if (i_par_start != -1 ) {
420
+ int i_par_end = p_text.find_char (' )' , i_start + 5 );
421
+ if (i_par_end != -1 ) {
422
+ Array color_info;
423
+ color_info.resize (INFO_COLOR_MAX);
424
+ color_info[TextEdit::INFO_LINE] = p_line;
425
+ color_info[TextEdit::INFO_COLUMN] = i_start;
426
+ color_info[TextEdit::INFO_WIDTH_RATIO] = 1.0 ;
427
+ color_info[INFO_COLOR_END] = i_par_end;
428
+
429
+ String fn_name = p_text.substr (i_start + 5 , i_par_start - i_start - 5 );
430
+ String s_params = p_text.substr (i_par_start + 1 , i_par_end - i_par_start - 1 );
431
+ bool has_added_color = false ;
432
+
433
+ if (fn_name.is_empty () || fn_name == " .from_string" ) {
434
+ String stripped = s_params.strip_edges (true , true );
435
+ // String parameter.
436
+ if (stripped.length () > 0 && (stripped[0 ] == ' \" ' )) {
437
+ String color_string = stripped.substr (1 , stripped.length () - 2 );
438
+ color_info[INFO_COLOR] = Color (color_string);
439
+ color_info[INFO_COLOR_MODE] = -1 ;
440
+ has_added_color = true ;
441
+ }
442
+ // Empty Color() constructor.
443
+ else if (stripped.is_empty ()) {
444
+ color_info[INFO_COLOR] = Color ();
445
+ color_info[INFO_COLOR_MODE] = -1 ;
446
+ has_added_color = true ;
447
+ }
448
+ }
449
+ // Float & int parameters.
450
+ if (!has_added_color && s_params.size () > 0 ) {
451
+ PackedFloat64Array params = s_params.split_floats (" ," , false );
452
+ if (params.size () == 3 ) {
453
+ params.resize (4 );
454
+ params.set (3 , 1.0 );
455
+ }
456
+ if (params.size () == 4 ) {
457
+ has_added_color = true ;
458
+ if (fn_name == " .from_ok_hsl" ) {
459
+ color_info[INFO_COLOR] = Color::from_ok_hsl (params[0 ], params[1 ], params[2 ], params[3 ]);
460
+ color_info[INFO_COLOR_MODE] = ColorPicker::MODE_OKHSL;
461
+ } else if (fn_name == " .from_hsv" ) {
462
+ color_info[INFO_COLOR] = Color::from_hsv (params[0 ], params[1 ], params[2 ], params[3 ]);
463
+ color_info[INFO_COLOR_MODE] = ColorPicker::MODE_HSV;
464
+ } else if (fn_name == " .from_rgba8" ) {
465
+ color_info[INFO_COLOR] = Color::from_rgba8 (int (params[0 ]), int (params[1 ]), int (params[2 ]), int (params[3 ]));
466
+ color_info[INFO_COLOR_MODE] = ColorPicker::MODE_RGB;
467
+ } else if (fn_name.is_empty ()) {
468
+ color_info[INFO_COLOR] = Color (params[0 ], params[1 ], params[2 ], params[3 ]);
469
+ color_info[INFO_COLOR_MODE] = ColorPicker::MODE_RAW;
470
+ } else {
471
+ has_added_color = false ;
472
+ }
473
+ }
474
+ }
475
+
476
+ if (has_added_color) {
477
+ result.push_back (color_info);
478
+ i_end_previous = i_par_end + 1 ;
479
+ }
480
+ }
481
+ }
482
+ i_end_previous = MAX (i_end_previous, i_start);
483
+ i_start = p_text.find (" Color" , i_start + 1 );
484
+ }
485
+ return result;
486
+ }
487
+
488
+ void ScriptTextEditor::_inline_object_draw (const Array &p_info, const Rect2 &p_rect) {
489
+ if (_is_valid_color_info (p_info)) {
490
+ Rect2 col_rect = p_rect.grow (-4 );
491
+ code_editor->get_text_editor ()->draw_rect (col_rect, Color (p_info[INFO_COLOR]));
492
+ code_editor->get_text_editor ()->draw_rect (col_rect, Color (1 , 1 , 1 ), false , 1 );
493
+ }
494
+ }
495
+
496
+ void ScriptTextEditor::_inline_object_handle_click (const Array &p_info, const Rect2 &p_rect) {
497
+ if (_is_valid_color_info (p_info)) {
498
+ int mode = p_info[INFO_COLOR_MODE];
499
+ if (mode < 0 || mode >= ColorPicker::MODE_MAX) {
500
+ inline_color_picker->set_using_hex_string (true );
501
+ } else {
502
+ inline_color_picker->set_using_hex_string (false );
503
+ inline_color_picker->set_color_mode ((ColorPicker::ColorModeType)mode);
504
+ }
505
+
506
+ inline_color_picker->set_pick_color (p_info[INFO_COLOR]);
507
+ inline_color_line = p_info[TextEdit::INFO_LINE];
508
+ inline_color_start = p_info[TextEdit::INFO_COLUMN];
509
+ inline_color_end = p_info[INFO_COLOR_END];
510
+
511
+ // Move popup above the line if it's too low.
512
+ float_t view_h = get_viewport_rect ().size .y ;
513
+ float_t pop_h = inline_color_popup->get_contents_minimum_size ().y ;
514
+ float_t pop_y = p_rect.get_end ().y ;
515
+ float_t pop_x = p_rect.position .x ;
516
+ if (pop_y + pop_h > view_h) {
517
+ pop_y = p_rect.position .y - pop_h;
518
+ }
519
+ // Move popup to the right if it's too high.
520
+ if (pop_y < 0 ) {
521
+ pop_x = p_rect.get_end ().x ;
522
+ }
523
+
524
+ inline_color_popup->popup (Rect2 (pop_x, pop_y, 0 , 0 ));
525
+ code_editor->get_text_editor ()->set_selection_mode (TextEdit::SelectionMode::SELECTION_MODE_NONE);
526
+ }
527
+ }
528
+
529
+ String ScriptTextEditor::_picker_color_stringify (const Color &p_color, int p_mode) {
530
+ String result;
531
+ String fname;
532
+ Vector<String> str_params;
533
+ // HTML string.
534
+ if (p_mode < 0 ) {
535
+ str_params.push_back (" \" " + p_color.to_html () + " \" " );
536
+ }
537
+ // RGBA int parameters (0-255).
538
+ else if (p_mode == ColorPicker::MODE_RGB) {
539
+ str_params = {
540
+ itos (p_color.get_r8 ()),
541
+ itos (p_color.get_g8 ()),
542
+ itos (p_color.get_b8 ()),
543
+ itos (p_color.get_a8 ())
544
+ };
545
+ fname = " .from_rgba8" ;
546
+ }
547
+ // HSL, HSV, and RAW Float parameters.
548
+ else {
549
+ PackedFloat64Array flt_params;
550
+ str_params.resize (4 );
551
+ switch (p_mode) {
552
+ case ColorPicker::MODE_HSV: {
553
+ flt_params = { p_color.get_h (), p_color.get_s (), p_color.get_v (), p_color.a };
554
+ fname = " .from_hsv" ;
555
+ } break ;
556
+ case ColorPicker::MODE_OKHSL: {
557
+ flt_params = { p_color.get_ok_hsl_h (), p_color.get_ok_hsl_s (), p_color.get_ok_hsl_l (), p_color.a };
558
+ fname = " .from_ok_hsl" ;
559
+ } break ;
560
+ case ColorPicker::MODE_RAW: {
561
+ flt_params = { p_color.r , p_color.g , p_color.b , p_color.a };
562
+ fname = " " ;
563
+ } break ;
564
+ }
565
+ for (int ind = 0 ; ind < flt_params.size (); ind++) {
566
+ str_params.set (ind, String::num (flt_params[ind], 3 ));
567
+ }
568
+ }
569
+ result = " Color" + fname + " (" + String (" , " ).join (str_params) + " )" ;
570
+ return result;
571
+ }
572
+
573
+ void ScriptTextEditor::_picker_color_changed (const Color &p_color) {
574
+ if (inline_color_line < 0 ) {
575
+ return ;
576
+ }
577
+ int mode = inline_color_picker->get_color_mode ();
578
+ if (inline_color_picker->is_using_hex_string ()) {
579
+ mode = -1 ;
580
+ }
581
+ String result = _picker_color_stringify (p_color, mode);
582
+ code_editor->get_text_editor ()->begin_complex_operation ();
583
+ code_editor->get_text_editor ()->remove_text (inline_color_line, inline_color_start, inline_color_line, inline_color_end + 1 );
584
+ inline_color_end = inline_color_start + result.size () - 2 ;
585
+ code_editor->get_text_editor ()->insert_text (result, inline_color_line, inline_color_start);
586
+ code_editor->get_text_editor ()->end_complex_operation ();
587
+ }
588
+
589
+ void ScriptTextEditor::_picker_opening () {
590
+ previous_tooltip_enabled = code_editor->get_text_editor ()->is_symbol_tooltip_on_hover_enabled ();
591
+ code_editor->get_text_editor ()->set_symbol_tooltip_on_hover_enabled (false );
592
+ }
593
+
594
+ void ScriptTextEditor::_picker_closed () {
595
+ code_editor->get_text_editor ()->set_symbol_tooltip_on_hover_enabled (previous_tooltip_enabled);
596
+ }
597
+
399
598
void ScriptTextEditor::update_settings () {
400
599
code_editor->get_text_editor ()->set_gutter_draw (connection_gutter, EDITOR_GET (" text_editor/appearance/gutters/show_info_gutter" ));
600
+ if (EDITOR_GET (" text_editor/appearance/enable_inline_color_picker" )) {
601
+ code_editor->get_text_editor ()->set_inline_object_handlers (
602
+ callable_mp (this , &ScriptTextEditor::_inline_object_parse),
603
+ callable_mp (this , &ScriptTextEditor::_inline_object_draw),
604
+ callable_mp (this , &ScriptTextEditor::_inline_object_handle_click));
605
+ } else {
606
+ code_editor->get_text_editor ()->set_inline_object_handlers (Callable (), Callable (), Callable ());
607
+ }
401
608
code_editor->update_editor_settings ();
402
609
}
403
610
@@ -2594,6 +2801,17 @@ ScriptTextEditor::ScriptTextEditor() {
2594
2801
bookmarks_menu = memnew (PopupMenu);
2595
2802
breakpoints_menu = memnew (PopupMenu);
2596
2803
2804
+ inline_color_popup = memnew (PopupPanel);
2805
+ inline_color_popup->connect (" about_to_popup" , callable_mp (this , &ScriptTextEditor::_picker_opening));
2806
+ inline_color_popup->connect (" popup_hide" , callable_mp (this , &ScriptTextEditor::_picker_closed));
2807
+ add_child (inline_color_popup);
2808
+
2809
+ inline_color_picker = memnew (ColorPicker);
2810
+ inline_color_picker->set_mouse_filter (MOUSE_FILTER_STOP);
2811
+ inline_color_picker->set_deferred_mode (true );
2812
+ inline_color_picker->connect (" color_changed" , callable_mp (this , &ScriptTextEditor::_picker_color_changed));
2813
+ inline_color_popup->add_child (inline_color_picker);
2814
+
2597
2815
connection_info_dialog = memnew (ConnectionInfoDialog);
2598
2816
2599
2817
SET_DRAG_FORWARDING_GCD (code_editor->get_text_editor (), ScriptTextEditor);
0 commit comments