-
-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add optimized LineEditButton control (#731)
- Loading branch information
Showing
40 changed files
with
464 additions
and
346 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
[remap] | ||
|
||
importer="texture" | ||
type="CompressedTexture2D" | ||
uid="uid://bfpat62uepne8" | ||
path="res://.godot/imported/LineEditButton.svg-8852cdccf228ac979cde671d6750b2e2.ctex" | ||
metadata={ | ||
"vram_texture": false | ||
} | ||
|
||
[deps] | ||
|
||
source_file="res://godot_only/icons/LineEditButton.svg" | ||
dest_files=["res://.godot/imported/LineEditButton.svg-8852cdccf228ac979cde671d6750b2e2.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 | ||
svg/scale=1.0 | ||
editor/scale_with_editor_scale=false | ||
editor/convert_colors_with_editor_theme=false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
@icon("res://godot_only/icons/LineEditButton.svg") | ||
class_name LineEditButton extends Control | ||
## An optimized control representing a LineEdit with a button attached to it. | ||
|
||
# A fake-out is drawn to avoid adding unnecessary nodes. | ||
# The real controls are only created when necessary, such as when hovered or focused. | ||
|
||
const BUTTON_WIDTH = 14.0 | ||
|
||
signal pressed | ||
signal text_change_canceled | ||
signal text_changed | ||
signal text_submitted | ||
signal button_gui_input | ||
|
||
var _should_stay_active_outside := false | ||
var _is_mouse_outside := true | ||
|
||
var active := false | ||
var temp_line_edit: BetterLineEdit | ||
var temp_button: Button | ||
|
||
@export var placeholder_text: String: | ||
set(new_value): | ||
if placeholder_text != new_value: | ||
placeholder_text = new_value | ||
if active: | ||
temp_line_edit.placeholder_text = new_value | ||
else: | ||
queue_redraw() | ||
|
||
@export var text: String: | ||
set(new_value): | ||
if text != new_value: | ||
text = new_value | ||
if active: | ||
temp_line_edit.text = new_value | ||
else: | ||
queue_redraw() | ||
|
||
@export var font_color := Color.TRANSPARENT: | ||
set(new_value): | ||
if font_color != new_value: | ||
font_color = new_value | ||
if active: | ||
temp_line_edit.add_theme_color_override("font_color", _get_font_color()) | ||
else: | ||
queue_redraw() | ||
|
||
@export var icon: Texture2D | ||
@export var button_visuals := true | ||
@export var code_font := true | ||
|
||
var ci := get_canvas_item() | ||
|
||
|
||
func reset_font_color() -> void: | ||
font_color = Color.TRANSPARENT # This is the value treated as invalid. | ||
|
||
|
||
func _init() -> void: | ||
custom_minimum_size.y = 22 | ||
set_anchors_and_offsets_preset(PRESET_TOP_LEFT) | ||
focus_mode = Control.FOCUS_ALL | ||
focus_entered.connect(_on_base_class_focus_entered) | ||
mouse_entered.connect(_on_base_class_mouse_entered) | ||
mouse_exited.connect(_on_base_class_mouse_exited) | ||
|
||
func _on_base_class_mouse_entered() -> void: | ||
_is_mouse_outside = false | ||
_setup() | ||
|
||
func _on_base_class_focus_entered() -> void: | ||
_setup() | ||
|
||
func _on_base_class_mouse_exited() -> void: | ||
_is_mouse_outside = true | ||
if not _should_stay_active_outside: | ||
_setdown() | ||
|
||
func _on_underlying_control_focused() -> void: | ||
_should_stay_active_outside = true | ||
focus_entered.emit() | ||
|
||
func _on_underlying_control_unfocused() -> void: | ||
_should_stay_active_outside = false | ||
if _is_mouse_outside: | ||
_setdown() | ||
|
||
func _setup() -> void: | ||
if not active: | ||
active = true | ||
temp_line_edit = BetterLineEdit.new() | ||
temp_line_edit.custom_minimum_size =\ | ||
Vector2(custom_minimum_size.x - BUTTON_WIDTH, 22) | ||
temp_line_edit.tooltip_text = tooltip_text | ||
temp_line_edit.placeholder_text = placeholder_text | ||
temp_line_edit.text = text | ||
temp_line_edit.mouse_filter = Control.MOUSE_FILTER_PASS | ||
temp_line_edit.theme_type_variation = "RightConnectedLineEdit" | ||
if font_color != Color.TRANSPARENT: | ||
temp_line_edit.add_theme_color_override("font_color", _get_font_color()) | ||
temp_line_edit.text_change_canceled.connect(emit_text_change_canceled) | ||
temp_line_edit.text_changed.connect(emit_text_changed) | ||
temp_line_edit.text_submitted.connect(emit_text_submitted) | ||
temp_line_edit.focus_entered.connect(_on_underlying_control_focused) | ||
temp_line_edit.focus_exited.connect(_on_underlying_control_unfocused) | ||
add_child(temp_line_edit) | ||
temp_button = Button.new() | ||
temp_button.show_behind_parent = true # Lets the icon draw in front. | ||
temp_button.custom_minimum_size = Vector2(BUTTON_WIDTH, 22) | ||
temp_button.position.x = size.x - BUTTON_WIDTH | ||
temp_button.focus_mode = Control.FOCUS_NONE | ||
temp_button.mouse_filter = Control.MOUSE_FILTER_PASS | ||
temp_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND | ||
if button_visuals: | ||
temp_button.theme_type_variation = "LeftConnectedButton" | ||
else: | ||
temp_button.flat = true | ||
temp_button.pressed.connect(emit_pressed) | ||
temp_button.gui_input.connect(emit_button_gui_input) | ||
temp_button.button_down.connect(_on_underlying_control_focused) | ||
temp_button.button_up.connect(_on_underlying_control_unfocused) | ||
add_child(temp_button) | ||
queue_redraw() | ||
# If there aren't button visuals, then they are probably | ||
# handed off to draw functions which need to be aware of the hover state. | ||
if not button_visuals: | ||
temp_button.mouse_exited.connect(queue_redraw) | ||
temp_line_edit.mouse_exited.connect(queue_redraw) | ||
|
||
func _setdown() -> void: | ||
if active: | ||
active = false | ||
temp_line_edit.queue_free() | ||
temp_button.queue_free() | ||
queue_redraw() | ||
|
||
|
||
func _draw() -> void: | ||
var sb: StyleBoxFlat = get_theme_stylebox("normal", "LineEdit") | ||
var horizontal_margin_width := sb.content_margin_left + sb.content_margin_right | ||
if not active: | ||
draw_style_box(sb, Rect2(Vector2.ZERO, size)) | ||
draw_line(Vector2(size.x - BUTTON_WIDTH, 0), | ||
Vector2(size.x - BUTTON_WIDTH, size.y), sb.border_color, 2) | ||
# The default overrun behavior couldn't be changed for the simplest draw methods. | ||
var text_line_object := TextLine.new() | ||
text_line_object.text_overrun_behavior = TextServer.OVERRUN_TRIM_CHAR | ||
text_line_object.width = size.x - BUTTON_WIDTH - horizontal_margin_width | ||
text_line_object.add_string(placeholder_text if text.is_empty() else text, | ||
get_theme_font("font", "LineEdit"), get_theme_font_size("font_size", "LineEdit")) | ||
text_line_object.draw(ci, Vector2(5, 2), get_theme_color("font_placeholder_color", | ||
"LineEdit") if text.is_empty() else _get_font_color()) | ||
|
||
if is_instance_valid(icon): | ||
var icon_side := BUTTON_WIDTH - horizontal_margin_width + 2 | ||
icon.draw_rect(ci, Rect2(size.x - (BUTTON_WIDTH + 0.5 + icon_side) / 2, | ||
(size.y - icon_side) / 2, icon_side, icon_side), false) | ||
|
||
|
||
func emit_pressed() -> void: | ||
pressed.emit() | ||
|
||
func emit_text_change_canceled() -> void: | ||
text_change_canceled.emit() | ||
|
||
func emit_text_changed(new_text: String) -> void: | ||
text_changed.emit(new_text) | ||
|
||
func emit_text_submitted(new_text: String) -> void: | ||
text_submitted.emit(new_text) | ||
|
||
func emit_button_gui_input(event: InputEvent) -> void: | ||
button_gui_input.emit(event) | ||
|
||
|
||
# Helpers | ||
|
||
func _get_font_color() -> Color: | ||
return get_theme_color("font_color", "LineEdit") if font_color == Color.TRANSPARENT\ | ||
else font_color | ||
|
||
func draw_button_border(theme_name: String) -> void: | ||
var button_outline: StyleBoxFlat =\ | ||
get_theme_stylebox(theme_name, "LeftConnectedButton").duplicate() | ||
button_outline.draw_center = false | ||
button_outline.draw(ci, Rect2(size.x - BUTTON_WIDTH, 0, BUTTON_WIDTH, size.y)) |
Oops, something went wrong.