mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 09:09:47 +00:00
Add a text tool (#1134)
* Initial port of the text tool to Godot 4 * Change font (WIP) * Add antialiasing option and remove some old unneeded lines * Remove outline code * Add horizontal alignment and update the text edit font size * Improve the text edit * Don't activate tools while typing * Format * Give input priority to the text edit so the key X and shortcuts such as control-z work in the text edit * Add style settings for bold and italic * Fix text going blank when changing font * Use `font.draw_multiline_string()` * Change the move behavior of the text tool, add confirm and cancel buttons * Compress images on undo/redo * Fix text position
This commit is contained in:
parent
f6beb4470e
commit
428e5edb8f
BIN
assets/graphics/tools/cursors/text.png
Normal file
BIN
assets/graphics/tools/cursors/text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 218 B |
34
assets/graphics/tools/cursors/text.png.import
Normal file
34
assets/graphics/tools/cursors/text.png.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dn66bu1htli0i"
|
||||
path="res://.godot/imported/text.png-e400a2b9b6a87e25638acb803c02cdbf.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/graphics/tools/cursors/text.png"
|
||||
dest_files=["res://.godot/imported/text.png-e400a2b9b6a87e25638acb803c02cdbf.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
assets/graphics/tools/text.png
Normal file
BIN
assets/graphics/tools/text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
34
assets/graphics/tools/text.png.import
Normal file
34
assets/graphics/tools/text.png.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bwpucajlx84xt"
|
||||
path="res://.godot/imported/text.png-627e4dab52ac32f8208bc01b5803fe72.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/graphics/tools/text.png"
|
||||
dest_files=["res://.godot/imported/text.png-627e4dab52ac32f8208bc01b5803fe72.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
|
@ -911,6 +911,16 @@ center_canvas={
|
|||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":67,"physical_keycode":0,"key_label":0,"unicode":67,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
left_text_tool={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
right_text_tool={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[input_devices]
|
||||
|
||||
|
|
|
@ -1071,7 +1071,7 @@ func get_available_font_names() -> PackedStringArray:
|
|||
func find_font_from_name(font_name: String) -> Font:
|
||||
for font in loaded_fonts:
|
||||
if font.get_font_name() == font_name:
|
||||
return font
|
||||
return font.duplicate()
|
||||
for system_font_name in OS.get_system_fonts():
|
||||
if system_font_name == font_name:
|
||||
var system_font := SystemFont.new()
|
||||
|
|
|
@ -201,6 +201,15 @@ Hold %s to displace the shape's origin""",
|
|||
["shape_perfect", "shape_center", "shape_displace"]
|
||||
)
|
||||
),
|
||||
"Text":
|
||||
Tool.new(
|
||||
"Text",
|
||||
"Text",
|
||||
"text",
|
||||
"res://src/Tools/UtilityTools/Text.tscn",
|
||||
[Global.LayerTypes.PIXEL],
|
||||
""
|
||||
),
|
||||
"3DShapeEdit":
|
||||
Tool.new(
|
||||
"3DShapeEdit",
|
||||
|
|
|
@ -199,6 +199,8 @@ func _ready() -> void:
|
|||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventKey and is_instance_valid(Global.main_viewport):
|
||||
Global.main_viewport.get_child(0).push_input(event)
|
||||
left_cursor.position = get_global_mouse_position() + Vector2(-32, 32)
|
||||
right_cursor.position = get_global_mouse_position() + Vector2(32, 32)
|
||||
|
||||
|
|
234
src/Tools/UtilityTools/Text.gd
Normal file
234
src/Tools/UtilityTools/Text.gd
Normal file
|
@ -0,0 +1,234 @@
|
|||
extends BaseTool
|
||||
|
||||
enum TextStyle { REGULAR, BOLD, ITALIC, BOLD_ITALIC }
|
||||
|
||||
const EMBOLDEN_AMOUNT := 0.6
|
||||
const ITALIC_AMOUNT := 0.2
|
||||
const ITALIC_TRANSFORM := Transform2D(Vector2(1.0, ITALIC_AMOUNT), Vector2(0.0, 1.0), Vector2.ZERO)
|
||||
|
||||
var text_edit: TextToolEdit:
|
||||
set(value):
|
||||
text_edit = value
|
||||
confirm_buttons.visible = is_instance_valid(text_edit)
|
||||
var text_size := 16
|
||||
var font := FontVariation.new()
|
||||
var font_name := "":
|
||||
set(value):
|
||||
font_name = value
|
||||
font.base_font = Global.find_font_from_name(font_name)
|
||||
font.base_font.antialiasing = antialiasing
|
||||
_textedit_text_changed()
|
||||
var text_style := TextStyle.REGULAR:
|
||||
set(value):
|
||||
text_style = value
|
||||
match text_style:
|
||||
TextStyle.REGULAR:
|
||||
font.variation_embolden = 0
|
||||
font.variation_transform = Transform2D()
|
||||
TextStyle.BOLD:
|
||||
font.variation_embolden = EMBOLDEN_AMOUNT
|
||||
font.variation_transform = Transform2D()
|
||||
TextStyle.ITALIC:
|
||||
font.variation_embolden = 0
|
||||
font.variation_transform = ITALIC_TRANSFORM
|
||||
TextStyle.BOLD_ITALIC:
|
||||
font.variation_embolden = EMBOLDEN_AMOUNT
|
||||
font.variation_transform = ITALIC_TRANSFORM
|
||||
save_config()
|
||||
_textedit_text_changed()
|
||||
|
||||
var horizontal_alignment := HORIZONTAL_ALIGNMENT_LEFT
|
||||
var antialiasing := TextServer.FONT_ANTIALIASING_NONE:
|
||||
set(value):
|
||||
antialiasing = value
|
||||
font.base_font.antialiasing = antialiasing
|
||||
|
||||
var _offset := Vector2i.ZERO
|
||||
|
||||
@onready var confirm_buttons: HBoxContainer = $ConfirmButtons
|
||||
@onready var font_option_button: OptionButton = $GridContainer/FontOptionButton
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var font_names := Global.get_available_font_names()
|
||||
for f_name in font_names:
|
||||
font_option_button.add_item(f_name)
|
||||
Tools.color_changed.connect(_on_color_changed)
|
||||
super._ready()
|
||||
|
||||
|
||||
func get_config() -> Dictionary:
|
||||
return {
|
||||
"font_name": font_name,
|
||||
"text_size": text_size,
|
||||
"text_style": text_style,
|
||||
"horizontal_alignment": horizontal_alignment,
|
||||
"antialiasing": antialiasing
|
||||
}
|
||||
|
||||
|
||||
func set_config(config: Dictionary) -> void:
|
||||
font_name = config.get("font_name", "Roboto")
|
||||
if font_name not in Global.get_available_font_names():
|
||||
font_name = "Roboto"
|
||||
text_size = config.get("text_size", text_size)
|
||||
text_style = config.get("text_style", text_style)
|
||||
horizontal_alignment = config.get("horizontal_alignment", horizontal_alignment)
|
||||
antialiasing = config.get("antialiasing", antialiasing)
|
||||
|
||||
|
||||
func update_config() -> void:
|
||||
for i in font_option_button.item_count:
|
||||
var item_name: String = font_option_button.get_item_text(i)
|
||||
if font_name == item_name:
|
||||
font_option_button.selected = i
|
||||
$TextSizeSlider.value = text_size
|
||||
|
||||
|
||||
func draw_start(pos: Vector2i) -> void:
|
||||
if not is_instance_valid(text_edit):
|
||||
text_edit = TextToolEdit.new()
|
||||
text_edit.text = ""
|
||||
text_edit.font = font
|
||||
text_edit.add_theme_color_override(&"font_color", tool_slot.color)
|
||||
text_edit.add_theme_font_size_override(&"font_size", text_size)
|
||||
Global.canvas.add_child(text_edit)
|
||||
text_edit.position = pos - Vector2i(0, text_edit.custom_minimum_size.y / 2)
|
||||
_offset = pos
|
||||
|
||||
|
||||
func draw_move(pos: Vector2i) -> void:
|
||||
if is_instance_valid(text_edit) and not text_edit.get_global_rect().has_point(pos):
|
||||
text_edit.position += Vector2(pos - _offset)
|
||||
_offset = pos
|
||||
|
||||
|
||||
func draw_end(_position: Vector2i) -> void:
|
||||
pass
|
||||
|
||||
|
||||
func text_to_pixels() -> void:
|
||||
if not is_instance_valid(text_edit):
|
||||
return
|
||||
if text_edit.text.is_empty():
|
||||
text_edit.queue_free()
|
||||
text_edit = null
|
||||
return
|
||||
|
||||
var undo_data := _get_undo_data()
|
||||
var project := Global.current_project
|
||||
var image := project.frames[project.current_frame].cels[project.current_layer].get_image()
|
||||
|
||||
var vp := RenderingServer.viewport_create()
|
||||
var canvas := RenderingServer.canvas_create()
|
||||
RenderingServer.viewport_attach_canvas(vp, canvas)
|
||||
RenderingServer.viewport_set_size(vp, project.size.x, project.size.y)
|
||||
RenderingServer.viewport_set_disable_3d(vp, true)
|
||||
RenderingServer.viewport_set_active(vp, true)
|
||||
RenderingServer.viewport_set_transparent_background(vp, true)
|
||||
|
||||
var ci_rid := RenderingServer.canvas_item_create()
|
||||
RenderingServer.viewport_set_canvas_transform(vp, canvas, Transform2D())
|
||||
RenderingServer.canvas_item_set_parent(ci_rid, canvas)
|
||||
var texture := RenderingServer.texture_2d_create(image)
|
||||
RenderingServer.canvas_item_add_texture_rect(
|
||||
ci_rid, Rect2(Vector2(0, 0), project.size), texture
|
||||
)
|
||||
|
||||
var text := text_edit.text
|
||||
var color := tool_slot.color
|
||||
var font_ascent := font.get_ascent(text_size)
|
||||
var pos := Vector2(1, font_ascent + text_edit.get_theme_constant(&"line_spacing"))
|
||||
pos += text_edit.position
|
||||
font.draw_multiline_string(ci_rid, pos, text, horizontal_alignment, -1, text_size, -1, color)
|
||||
|
||||
RenderingServer.viewport_set_update_mode(vp, RenderingServer.VIEWPORT_UPDATE_ONCE)
|
||||
RenderingServer.force_draw(false)
|
||||
var viewport_texture := RenderingServer.texture_2d_get(RenderingServer.viewport_get_texture(vp))
|
||||
RenderingServer.free_rid(vp)
|
||||
RenderingServer.free_rid(canvas)
|
||||
RenderingServer.free_rid(ci_rid)
|
||||
RenderingServer.free_rid(texture)
|
||||
viewport_texture.convert(Image.FORMAT_RGBA8)
|
||||
|
||||
text_edit.queue_free()
|
||||
text_edit = null
|
||||
if not viewport_texture.is_empty():
|
||||
image.copy_from(viewport_texture)
|
||||
commit_undo("Draw", undo_data)
|
||||
|
||||
|
||||
func commit_undo(action: String, undo_data: Dictionary) -> void:
|
||||
var redo_data := _get_undo_data()
|
||||
var project := Global.current_project
|
||||
var frame := -1
|
||||
var layer := -1
|
||||
if Global.animation_timeline.animation_timer.is_stopped() and project.selected_cels.size() == 1:
|
||||
frame = project.current_frame
|
||||
layer = project.current_layer
|
||||
|
||||
project.undos += 1
|
||||
project.undo_redo.create_action(action)
|
||||
Global.undo_redo_compress_images(redo_data, undo_data, project)
|
||||
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false, frame, layer))
|
||||
project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true, frame, layer))
|
||||
project.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _get_undo_data() -> Dictionary:
|
||||
var data := {}
|
||||
var images := _get_selected_draw_images()
|
||||
for image in images:
|
||||
data[image] = image.data
|
||||
return data
|
||||
|
||||
|
||||
func _on_confirm_button_pressed() -> void:
|
||||
if is_instance_valid(text_edit):
|
||||
text_to_pixels()
|
||||
|
||||
|
||||
func _on_cancel_button_pressed() -> void:
|
||||
if is_instance_valid(text_edit):
|
||||
text_edit.queue_free()
|
||||
text_edit = null
|
||||
|
||||
|
||||
func _textedit_text_changed() -> void:
|
||||
if not is_instance_valid(text_edit):
|
||||
return
|
||||
text_edit.add_theme_font_size_override(&"font_size", 1) # Needed to update font and text style
|
||||
text_edit.add_theme_font_size_override(&"font_size", text_size)
|
||||
text_edit._on_text_changed()
|
||||
|
||||
|
||||
func _on_color_changed(_color: Color, _button: int) -> void:
|
||||
if is_instance_valid(text_edit):
|
||||
text_edit.add_theme_color_override(&"font_color", tool_slot.color)
|
||||
|
||||
|
||||
func _on_text_size_slider_value_changed(value: float) -> void:
|
||||
text_size = value
|
||||
_textedit_text_changed()
|
||||
save_config()
|
||||
|
||||
|
||||
func _on_font_option_button_item_selected(index: int) -> void:
|
||||
font_name = font_option_button.get_item_text(index)
|
||||
save_config()
|
||||
|
||||
|
||||
func _on_style_option_button_item_selected(index: TextStyle) -> void:
|
||||
text_style = index
|
||||
|
||||
|
||||
func _on_horizontal_alignment_option_button_item_selected(index: HorizontalAlignment) -> void:
|
||||
horizontal_alignment = index
|
||||
|
||||
|
||||
func _on_antialiasing_option_button_item_selected(index: TextServer.FontAntialiasing) -> void:
|
||||
antialiasing = index
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
text_to_pixels()
|
139
src/Tools/UtilityTools/Text.tscn
Normal file
139
src/Tools/UtilityTools/Text.tscn
Normal file
|
@ -0,0 +1,139 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://ct4o5i1jeul3k"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://ctfgfelg0sho8" path="res://src/Tools/BaseTool.tscn" id="1_1q6ub"]
|
||||
[ext_resource type="Script" path="res://src/Tools/UtilityTools/Text.gd" id="2_ql5g6"]
|
||||
[ext_resource type="Texture2D" uid="uid://d267xalp3p7ru" path="res://assets/graphics/misc/check_plain.png" id="3_novww"]
|
||||
[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="3_tidsq"]
|
||||
[ext_resource type="Texture2D" uid="uid://bnc78807k1xjv" path="res://assets/graphics/misc/close.png" id="4_nhcnn"]
|
||||
|
||||
[node name="ToolOptions" instance=ExtResource("1_1q6ub")]
|
||||
script = ExtResource("2_ql5g6")
|
||||
|
||||
[node name="ConfirmButtons" type="HBoxContainer" parent="." index="2"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ConfirmButton" type="Button" parent="ConfirmButtons" index="0" groups=["UIButtons"]]
|
||||
custom_minimum_size = Vector2(0, 26)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_default_cursor_shape = 2
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ConfirmButtons/ConfirmButton" index="0"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
texture = ExtResource("3_novww")
|
||||
stretch_mode = 3
|
||||
|
||||
[node name="CancelButton" type="Button" parent="ConfirmButtons" index="1" groups=["UIButtons"]]
|
||||
custom_minimum_size = Vector2(0, 26)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_default_cursor_shape = 2
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ConfirmButtons/CancelButton" index="0"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
texture = ExtResource("4_nhcnn")
|
||||
stretch_mode = 3
|
||||
|
||||
[node name="TextSizeSlider" type="TextureProgressBar" parent="." index="3"]
|
||||
custom_minimum_size = Vector2(0, 24)
|
||||
layout_mode = 2
|
||||
focus_mode = 2
|
||||
mouse_default_cursor_shape = 2
|
||||
theme_type_variation = &"ValueSlider"
|
||||
min_value = 1.0
|
||||
max_value = 128.0
|
||||
value = 16.0
|
||||
allow_greater = true
|
||||
nine_patch_stretch = true
|
||||
stretch_margin_left = 3
|
||||
stretch_margin_top = 3
|
||||
stretch_margin_right = 3
|
||||
stretch_margin_bottom = 3
|
||||
script = ExtResource("3_tidsq")
|
||||
prefix = "Size:"
|
||||
suffix = "px"
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="." index="4"]
|
||||
layout_mode = 2
|
||||
columns = 2
|
||||
|
||||
[node name="FontLabel" type="Label" parent="GridContainer" index="0"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Font:"
|
||||
|
||||
[node name="FontOptionButton" type="OptionButton" parent="GridContainer" index="1"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_default_cursor_shape = 2
|
||||
fit_to_longest_item = false
|
||||
|
||||
[node name="StyleLabel" type="Label" parent="GridContainer" index="2"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Style:"
|
||||
|
||||
[node name="StyleOptionButton" type="OptionButton" parent="GridContainer" index="3"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_default_cursor_shape = 2
|
||||
selected = 0
|
||||
item_count = 4
|
||||
popup/item_0/text = "Regular"
|
||||
popup/item_1/text = "Bold"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "Italic"
|
||||
popup/item_2/id = 2
|
||||
popup/item_3/text = "Bold Italic"
|
||||
popup/item_3/id = 3
|
||||
|
||||
[node name="HorizontalAlignmentLabel" type="Label" parent="GridContainer" index="4"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Horizontal alignment:"
|
||||
|
||||
[node name="HorizontalAlignmentOptionButton" type="OptionButton" parent="GridContainer" index="5"]
|
||||
layout_mode = 2
|
||||
selected = 0
|
||||
item_count = 4
|
||||
popup/item_0/text = "Left"
|
||||
popup/item_1/text = "Center"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "Right"
|
||||
popup/item_2/id = 2
|
||||
popup/item_3/text = "Fill"
|
||||
popup/item_3/id = 3
|
||||
|
||||
[node name="AntialiasingLabel" type="Label" parent="GridContainer" index="6"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Antialiasing:"
|
||||
|
||||
[node name="AntialiasingOptionButton" type="OptionButton" parent="GridContainer" index="7"]
|
||||
layout_mode = 2
|
||||
selected = 0
|
||||
item_count = 3
|
||||
popup/item_0/text = "None"
|
||||
popup/item_1/text = "Grayscale"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "LCD"
|
||||
popup/item_2/id = 2
|
||||
|
||||
[connection signal="pressed" from="ConfirmButtons/ConfirmButton" to="." method="_on_confirm_button_pressed"]
|
||||
[connection signal="pressed" from="ConfirmButtons/CancelButton" to="." method="_on_cancel_button_pressed"]
|
||||
[connection signal="value_changed" from="TextSizeSlider" to="." method="_on_text_size_slider_value_changed"]
|
||||
[connection signal="item_selected" from="GridContainer/FontOptionButton" to="." method="_on_font_option_button_item_selected"]
|
||||
[connection signal="item_selected" from="GridContainer/StyleOptionButton" to="." method="_on_style_option_button_item_selected"]
|
||||
[connection signal="item_selected" from="GridContainer/HorizontalAlignmentOptionButton" to="." method="_on_horizontal_alignment_option_button_item_selected"]
|
||||
[connection signal="item_selected" from="GridContainer/AntialiasingOptionButton" to="." method="_on_antialiasing_option_button_item_selected"]
|
46
src/UI/Nodes/TextToolEdit.gd
Normal file
46
src/UI/Nodes/TextToolEdit.gd
Normal file
|
@ -0,0 +1,46 @@
|
|||
class_name TextToolEdit
|
||||
extends TextEdit
|
||||
|
||||
var font: Font:
|
||||
set(value):
|
||||
font = value
|
||||
add_theme_font_override(&"font", font)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var stylebox := StyleBoxFlat.new()
|
||||
stylebox.draw_center = false
|
||||
stylebox.border_width_left = 1
|
||||
stylebox.border_width_top = 1
|
||||
stylebox.border_width_right = 1
|
||||
stylebox.border_width_bottom = 1
|
||||
add_theme_stylebox_override(&"normal", stylebox)
|
||||
add_theme_stylebox_override(&"focus", stylebox)
|
||||
add_theme_constant_override(&"line_spacing", 0)
|
||||
text_changed.connect(_on_text_changed)
|
||||
theme = Global.control.theme
|
||||
if is_instance_valid(font):
|
||||
var font_size := get_theme_font_size(&"font_size")
|
||||
custom_minimum_size = Vector2(32, maxf(32, font.get_height(font_size)))
|
||||
size.y = (get_line_count() + 1) * font.get_height(font_size)
|
||||
|
||||
|
||||
func _get_max_line() -> int:
|
||||
var max_line := 0
|
||||
var max_string := get_line(0).length()
|
||||
for i in get_line_count():
|
||||
var line := get_line(i)
|
||||
if line.length() > max_string:
|
||||
max_string = line.length()
|
||||
max_line = i
|
||||
return max_line
|
||||
|
||||
|
||||
func _on_text_changed() -> void:
|
||||
if not is_instance_valid(font):
|
||||
return
|
||||
var font_size := get_theme_font_size(&"font_size")
|
||||
var max_line := get_line(_get_max_line())
|
||||
var string_size := font.get_string_size(max_line, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size)
|
||||
size.x = font_size + string_size.x
|
||||
size.y = (get_line_count() + 1) * font.get_height(font_size)
|
|
@ -9,7 +9,7 @@ func _ready() -> void:
|
|||
Global.main_viewport.mouse_exited.connect(set_process_input.bind(false))
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseMotion:
|
||||
pen_inverted = event.pen_inverted
|
||||
return
|
||||
|
|
Loading…
Reference in a new issue