@tool extends LineEdit class_name LineEditWithButtons signal left_button_pressed() signal left_button_toggled() signal right_button_pressed() signal right_button_toggled() static var _empty_sb = StyleBoxEmpty.new() @export_subgroup("Left Icon") @export var left: Texture2D: set(value): left = value if not is_node_ready(): return if _left_btn and value == null: _left_btn.queue_free() return if not _left_btn and value: _left_btn = _create_button_icon(value) _left_btn.toggle_mode = left_is_toggle _left_btn.pressed.connect(left_button_pressed.emit) _left_btn.toggled.connect(left_button_toggled.emit) return _left_btn.icon = value @export var left_is_toggle: bool = false @export_subgroup("Right Icon") @export var right: Texture2D: set(value): right = value if not is_node_ready(): return if _right_btn and value == null: _right_btn.queue_free() return if not _right_btn and value: _right_btn = _create_button_icon(value) _right_btn.toggle_mode = right_is_toggle _right_btn.pressed.connect(right_button_pressed.emit) _right_btn.toggled.connect(right_button_toggled.emit) return _right_btn.icon = value @export var right_is_toggle: bool = false var _left_btn: Button var _right_btn: Button var _container: HBoxContainer var _spacer: Control var _nsb: StyleBox var _rosb: StyleBox var _fsb: StyleBox var _nsb_orig_left: float var _nsb_orig_right: float var _rosb_orig_left: float var _rosb_orig_right: float var _fsb_orig_left: float var _fsb_orig_right: float # Called when the node enters the scene tree for the first time. func _ready() -> void: _container = HBoxContainer.new() _spacer = Control.new() _spacer.mouse_filter = Control.MOUSE_FILTER_IGNORE _spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL _container.mouse_filter = Control.MOUSE_FILTER_IGNORE _container.add_child(_spacer) add_child(_container) if left != null: _left_btn = _create_button_icon(left) _left_btn.toggle_mode = left_is_toggle _left_btn.pressed.connect(left_button_pressed.emit) _left_btn.toggled.connect(left_button_toggled.emit) if right != null: _right_btn = _create_button_icon(right, -1) _right_btn.toggle_mode = right_is_toggle _right_btn.pressed.connect(right_button_pressed.emit) _right_btn.toggled.connect(right_button_toggled.emit) _nsb = get_theme_stylebox(&"normal").duplicate(true) _rosb = get_theme_stylebox(&"read_only").duplicate(true) _fsb = get_theme_stylebox(&"focus").duplicate(true) _nsb_orig_left = _nsb.content_margin_left _nsb_orig_right = _nsb.content_margin_right _rosb_orig_left = _rosb.content_margin_left _rosb_orig_right = _rosb.content_margin_right _fsb_orig_left = _fsb.content_margin_left _fsb_orig_right = _fsb.content_margin_right add_theme_stylebox_override(&"normal", _nsb) add_theme_stylebox_override(&"read_only", _rosb) add_theme_stylebox_override(&"focus", _fsb) item_rect_changed.connect(_handle_resize) func _create_button_icon(icon_texture: Texture2D, pos: int = 0) -> Button: var btn = Button.new() btn.icon = icon_texture btn.flat = true btn.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER btn.vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER btn.expand_icon = true btn.custom_minimum_size = Vector2(0, size.y) btn.ready.connect(func(): btn.icon = icon_texture) btn.add_theme_stylebox_override(&"normal", _empty_sb) btn.add_theme_stylebox_override(&"pressed", _empty_sb) btn.add_theme_stylebox_override(&"hover", _empty_sb) btn.add_theme_stylebox_override(&"disabled", _empty_sb) btn.add_theme_stylebox_override(&"focus", _empty_sb) _container.add_child(btn) _container.move_child(btn, pos) return btn func _handle_resize() -> void: _container.size = size if _left_btn: _left_btn.custom_minimum_size = Vector2(size.y, size.y) _fsb.content_margin_left = _fsb_orig_left + size.y _rosb.content_margin_left = _rosb_orig_left + size.y _nsb.content_margin_left = _nsb_orig_left + size.y if _right_btn: _right_btn.custom_minimum_size = Vector2(size.y, size.y) _fsb.content_margin_right = _fsb_orig_right + size.y _rosb.content_margin_right = _rosb_orig_right + size.y _nsb.content_margin_right = _nsb_orig_right + size.y