Add icon font plugin.
This commit is contained in:
parent
5edf4e654e
commit
dcc991a7d9
|
@ -0,0 +1,16 @@
|
||||||
|
@tool
|
||||||
|
extends RichTextLabel
|
||||||
|
|
||||||
|
@export_multiline
|
||||||
|
var text_with_icons: String:
|
||||||
|
set(value):
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
text_with_icons = value
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = IconsFonts.parse_text(value)
|
||||||
|
|
||||||
|
get: return text_with_icons
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = IconsFonts.parse_text(text_with_icons)
|
|
@ -0,0 +1 @@
|
||||||
|
uid://5px8jipd26f7
|
|
@ -0,0 +1,385 @@
|
||||||
|
[gd_scene load_steps=28 format=3 uid="uid://casymgu2sqx81"]
|
||||||
|
|
||||||
|
[ext_resource type="FontFile" uid="uid://be10y8fgoiayy" path="res://addons/icons-fonts/icons_fonts/emojis/NotoColorEmoji.ttf" id="1_lglyu"]
|
||||||
|
[ext_resource type="Script" uid="uid://sfoyl3fbn8so" path="res://addons/icons-fonts/nodes/FontIcon.gd" id="2_fd237"]
|
||||||
|
[ext_resource type="Script" uid="uid://dpyof2t0wn8k1" path="res://addons/icons-fonts/resources/FontIconSetting.gd" id="3_jajcj"]
|
||||||
|
[ext_resource type="Script" uid="uid://pwyh8365is28" path="res://addons/icons-fonts/nodes/FontIconButton.gd" id="4_5ca3b"]
|
||||||
|
[ext_resource type="Script" uid="uid://c4n2aki4724e4" path="res://addons/icons-fonts/nodes/FontIconCheckButton.gd" id="5_qfxwr"]
|
||||||
|
[ext_resource type="Script" uid="uid://5px8jipd26f7" path="res://addons/icons-fonts/examples/rich_text_label_with_icons.gd" id="6_3361y"]
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_fw4y0"]
|
||||||
|
font = ExtResource("1_lglyu")
|
||||||
|
font_size = 64
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_lqfro"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "image-outline"
|
||||||
|
icon_size = 128
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_28mvn"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "image-outline"
|
||||||
|
icon_size = 16
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_6nmg6"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yfigq"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0.1, 0.1, 0.1, 0.6)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
corner_detail = 5
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_nwary"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "toggle-switch-variant"
|
||||||
|
icon_size = 16
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_v03hs"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "toggle-switch-variant-off"
|
||||||
|
icon_size = 16
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_7vk3f"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "image-outline"
|
||||||
|
icon_size = 16
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_mmhoi"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_onf1e"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0.1, 0.1, 0.1, 0.6)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
corner_detail = 5
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_a0w4j"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "Emojis"
|
||||||
|
icon_name = "framed_picture"
|
||||||
|
icon_size = 64
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_pqb8k"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "Emojis"
|
||||||
|
icon_name = "framed_picture"
|
||||||
|
icon_size = 32
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_dtieq"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_r4h4a"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0.1, 0.1, 0.1, 0.6)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
corner_detail = 5
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_bo5k2"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "Emojis"
|
||||||
|
icon_name = "thumbs_up"
|
||||||
|
icon_size = 16
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_6kb3v"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "Emojis"
|
||||||
|
icon_name = "thumbs_down"
|
||||||
|
icon_size = 16
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_r0p3s"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "Emojis"
|
||||||
|
icon_name = "framed_picture"
|
||||||
|
icon_size = 32
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_b80wx"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "cards-heart"
|
||||||
|
icon_size = 26
|
||||||
|
icon_color = Color(0.963688, 0.444703, 0.363128, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_uhuk0"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "cards-heart-outline"
|
||||||
|
icon_size = 26
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_b1txr"]
|
||||||
|
script = ExtResource("3_jajcj")
|
||||||
|
icon_font = "MaterialIcons"
|
||||||
|
icon_name = "image-outline"
|
||||||
|
icon_size = 16
|
||||||
|
icon_color = Color(1, 1, 1, 1)
|
||||||
|
outline_color = Color(1, 1, 1, 1)
|
||||||
|
outline_size = 0
|
||||||
|
shadow_color = Color(1, 1, 1, 1)
|
||||||
|
shadow_size = 0
|
||||||
|
shadow_offset = Vector2(0, 0)
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_y3ob5"]
|
||||||
|
|
||||||
|
[node name="TestIconsFonts" type="BoxContainer"]
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 105.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 0
|
||||||
|
|
||||||
|
[node name="MaterialIconsExamples" type="BoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
vertical = true
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MaterialIconsExamples"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Material Icons"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="BoxContainer" type="BoxContainer" parent="MaterialIconsExamples"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="FontIcon" type="Label" parent="MaterialIconsExamples/BoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(50, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = ""
|
||||||
|
label_settings = SubResource("LabelSettings_fw4y0")
|
||||||
|
script = ExtResource("2_fd237")
|
||||||
|
icon_settings = SubResource("Resource_lqfro")
|
||||||
|
|
||||||
|
[node name="FontIconButton" type="PanelContainer" parent="MaterialIconsExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("4_5ca3b")
|
||||||
|
layout_alignment = null
|
||||||
|
icon_settings = SubResource("Resource_28mvn")
|
||||||
|
label_text = "Jakiś Tekst"
|
||||||
|
label_settings = SubResource("LabelSettings_6nmg6")
|
||||||
|
button_margin = 0
|
||||||
|
|
||||||
|
[node name="FontIconCheckButton" type="PanelContainer" parent="MaterialIconsExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_yfigq")
|
||||||
|
script = ExtResource("5_qfxwr")
|
||||||
|
on_icon_settings = SubResource("Resource_nwary")
|
||||||
|
off_icon_settings = SubResource("Resource_v03hs")
|
||||||
|
layout_order = "Label-Icon-Toggle"
|
||||||
|
layout_alignment = null
|
||||||
|
icon_settings = SubResource("Resource_7vk3f")
|
||||||
|
label_text = "Toogle"
|
||||||
|
label_settings = SubResource("LabelSettings_mmhoi")
|
||||||
|
button_margin = 0
|
||||||
|
toggle_mode = true
|
||||||
|
|
||||||
|
[node name="FontIconCheckButton2" type="PanelContainer" parent="MaterialIconsExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_onf1e")
|
||||||
|
script = ExtResource("5_qfxwr")
|
||||||
|
on_icon_settings = SubResource("Resource_nwary")
|
||||||
|
off_icon_settings = SubResource("Resource_v03hs")
|
||||||
|
layout_order = "Label-Toggle"
|
||||||
|
icon_settings = SubResource("Resource_7vk3f")
|
||||||
|
label_text = "Toogle"
|
||||||
|
label_settings = SubResource("LabelSettings_mmhoi")
|
||||||
|
button_margin = 0
|
||||||
|
toggle_mode = true
|
||||||
|
|
||||||
|
[node name="FontIconCheckButton3" type="PanelContainer" parent="MaterialIconsExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_onf1e")
|
||||||
|
script = ExtResource("5_qfxwr")
|
||||||
|
on_icon_settings = SubResource("Resource_nwary")
|
||||||
|
off_icon_settings = SubResource("Resource_v03hs")
|
||||||
|
layout_order = "Toggle"
|
||||||
|
icon_settings = SubResource("Resource_7vk3f")
|
||||||
|
label_text = "Toogle"
|
||||||
|
label_settings = SubResource("LabelSettings_mmhoi")
|
||||||
|
button_margin = 0
|
||||||
|
toggle_mode = true
|
||||||
|
|
||||||
|
[node name="EmojisExamples" type="BoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
vertical = true
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="EmojisExamples"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Emoji"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="BoxContainer" type="BoxContainer" parent="EmojisExamples"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="FontIcon2" type="Label" parent="EmojisExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "🖼️"
|
||||||
|
label_settings = SubResource("LabelSettings_fw4y0")
|
||||||
|
script = ExtResource("2_fd237")
|
||||||
|
icon_settings = SubResource("Resource_a0w4j")
|
||||||
|
|
||||||
|
[node name="FontIconButton2" type="PanelContainer" parent="EmojisExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("4_5ca3b")
|
||||||
|
layout_vertical = true
|
||||||
|
layout_alignment = null
|
||||||
|
icon_settings = SubResource("Resource_pqb8k")
|
||||||
|
label_text = "Jakiś Tekst"
|
||||||
|
label_settings = SubResource("LabelSettings_dtieq")
|
||||||
|
button_margin = 6
|
||||||
|
|
||||||
|
[node name="FontIconCheckButton2" type="PanelContainer" parent="EmojisExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_r4h4a")
|
||||||
|
script = ExtResource("5_qfxwr")
|
||||||
|
on_icon_settings = SubResource("Resource_bo5k2")
|
||||||
|
off_icon_settings = SubResource("Resource_6kb3v")
|
||||||
|
layout_order = "Label-Icon-Toggle"
|
||||||
|
layout_alignment = null
|
||||||
|
icon_settings = SubResource("Resource_r0p3s")
|
||||||
|
label_text = "Toogle"
|
||||||
|
label_settings = SubResource("LabelSettings_mmhoi")
|
||||||
|
button_margin = 0
|
||||||
|
toggle_mode = true
|
||||||
|
|
||||||
|
[node name="FontIconCheckButton3" type="PanelContainer" parent="EmojisExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_onf1e")
|
||||||
|
script = ExtResource("5_qfxwr")
|
||||||
|
on_icon_settings = SubResource("Resource_bo5k2")
|
||||||
|
off_icon_settings = SubResource("Resource_6kb3v")
|
||||||
|
layout_order = "Label-Toggle"
|
||||||
|
icon_settings = SubResource("Resource_r0p3s")
|
||||||
|
label_text = "Toogle"
|
||||||
|
label_settings = SubResource("LabelSettings_mmhoi")
|
||||||
|
button_margin = 0
|
||||||
|
toggle_mode = true
|
||||||
|
|
||||||
|
[node name="FontIconCheckButton4" type="PanelContainer" parent="EmojisExamples/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_onf1e")
|
||||||
|
script = ExtResource("5_qfxwr")
|
||||||
|
on_icon_settings = SubResource("Resource_bo5k2")
|
||||||
|
off_icon_settings = SubResource("Resource_6kb3v")
|
||||||
|
layout_order = "Toggle"
|
||||||
|
icon_settings = SubResource("Resource_r0p3s")
|
||||||
|
label_text = "Toogle"
|
||||||
|
label_settings = SubResource("LabelSettings_mmhoi")
|
||||||
|
button_margin = 0
|
||||||
|
toggle_mode = true
|
||||||
|
|
||||||
|
[node name="RichTextLabelWithIcons" type="RichTextLabel" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = "This text can have icons [font=res://addons/icons-fonts/icons_fonts/MaterialIcons/material_design_icons.ttf][/font],
|
||||||
|
but also emojis [font=res://addons/icons-fonts/icons_fonts/emojis/NotoColorEmoji.ttf]🖼️[/font]"
|
||||||
|
fit_content = true
|
||||||
|
script = ExtResource("6_3361y")
|
||||||
|
text_with_icons = "This text can have icons [mi:image],
|
||||||
|
but also emojis :framed_picture:"
|
||||||
|
|
||||||
|
[node name="FontIconCheckButton" type="PanelContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_onf1e")
|
||||||
|
script = ExtResource("5_qfxwr")
|
||||||
|
on_icon_settings = SubResource("Resource_b80wx")
|
||||||
|
off_icon_settings = SubResource("Resource_uhuk0")
|
||||||
|
layout_order = "Toggle"
|
||||||
|
layout_alignment = 0
|
||||||
|
icon_settings = SubResource("Resource_b1txr")
|
||||||
|
label_settings = SubResource("LabelSettings_y3ob5")
|
||||||
|
toggle_mode = true
|
|
@ -0,0 +1,140 @@
|
||||||
|
[gd_scene load_steps=5 format=3 uid="uid://bni8w3a3pcbwn"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://cq6lkta6wqfww" path="res://addons/icons-fonts/icon_finder/icon_finder.gd" id="1_nv02s"]
|
||||||
|
[ext_resource type="FontFile" uid="uid://bbfeoo2kuf30n" path="res://addons/icons-fonts/icons_fonts/MaterialIcons/material_design_icons.ttf" id="2_8e28h"]
|
||||||
|
[ext_resource type="Script" uid="uid://8ujwc2fokr54" path="res://addons/icons-fonts/icon_finder/IconsFontsRender.gd" id="3_hobrt"]
|
||||||
|
[ext_resource type="FontFile" uid="uid://be10y8fgoiayy" path="res://addons/icons-fonts/icons_fonts/emojis/NotoColorEmoji.ttf" id="3_sggto"]
|
||||||
|
|
||||||
|
[node name="IconFinder" type="Panel" node_paths=PackedStringArray("icons_renderers", "icons_renderers_tabs", "notify_label", "search_line_edit", "size_slider", "size_label", "scroll_container", "fonts_dropdown")]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
script = ExtResource("1_nv02s")
|
||||||
|
icons_renderers = [NodePath("MarginContainer/VBoxContainer/ScrollContainer/Tabs/MaterialIcons"), NodePath("MarginContainer/VBoxContainer/ScrollContainer/Tabs/Emojis")]
|
||||||
|
icons_renderers_tabs = NodePath("MarginContainer/VBoxContainer/ScrollContainer/Tabs")
|
||||||
|
notify_label = NodePath("MarginContainer/VBoxContainer/Notify")
|
||||||
|
search_line_edit = NodePath("MarginContainer/VBoxContainer/HBoxContainer/Search")
|
||||||
|
size_slider = NodePath("MarginContainer/VBoxContainer/SliderContainer/HSlider")
|
||||||
|
size_label = NodePath("MarginContainer/VBoxContainer/SliderContainer/LabelSize")
|
||||||
|
scroll_container = NodePath("MarginContainer/VBoxContainer/ScrollContainer")
|
||||||
|
fonts_dropdown = NodePath("MarginContainer/VBoxContainer/HBoxContainer/FontsDropdown")
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/margin_left = 10
|
||||||
|
theme_override_constants/margin_top = 10
|
||||||
|
theme_override_constants/margin_right = 10
|
||||||
|
theme_override_constants/margin_bottom = 10
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Font"
|
||||||
|
|
||||||
|
[node name="FontsDropdown" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
selected = 0
|
||||||
|
item_count = 2
|
||||||
|
popup/item_0/text = "MaterialIcons"
|
||||||
|
popup/item_1/text = "Emojis"
|
||||||
|
popup/item_1/id = 1
|
||||||
|
|
||||||
|
[node name="Search" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
placeholder_text = "Search"
|
||||||
|
caret_blink = true
|
||||||
|
caret_blink_interval = 0.5
|
||||||
|
|
||||||
|
[node name="Notify" type="Label" parent="MarginContainer/VBoxContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Icon-x was copied to clipboard."
|
||||||
|
|
||||||
|
[node name="SliderContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/SliderContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Size preview"
|
||||||
|
|
||||||
|
[node name="HSlider" type="HSlider" parent="MarginContainer/VBoxContainer/SliderContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 1
|
||||||
|
min_value = 16.0
|
||||||
|
max_value = 128.0
|
||||||
|
value = 16.0
|
||||||
|
|
||||||
|
[node name="LabelSize" type="Label" parent="MarginContainer/VBoxContainer/SliderContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "16"
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
follow_focus = true
|
||||||
|
|
||||||
|
[node name="Tabs" type="TabContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
current_tab = 0
|
||||||
|
tabs_visible = false
|
||||||
|
|
||||||
|
[node name="MaterialIcons" type="RichTextLabel" parent="MarginContainer/VBoxContainer/ScrollContainer/Tabs" node_paths=PackedStringArray("size_slider", "search_line_edit")]
|
||||||
|
clip_contents = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
tooltip_text = "click on icon to copy its name to clipboard"
|
||||||
|
theme_override_fonts/normal_font = ExtResource("2_8e28h")
|
||||||
|
theme_override_font_sizes/normal_font_size = 16
|
||||||
|
bbcode_enabled = true
|
||||||
|
fit_content = true
|
||||||
|
scroll_active = false
|
||||||
|
autowrap_mode = 0
|
||||||
|
meta_underlined = false
|
||||||
|
threaded = true
|
||||||
|
script = ExtResource("3_hobrt")
|
||||||
|
size_slider = NodePath("../../../SliderContainer/HSlider")
|
||||||
|
search_line_edit = NodePath("../../../HBoxContainer/Search")
|
||||||
|
metadata/_tab_index = 0
|
||||||
|
|
||||||
|
[node name="Emojis" type="RichTextLabel" parent="MarginContainer/VBoxContainer/ScrollContainer/Tabs" node_paths=PackedStringArray("size_slider", "search_line_edit")]
|
||||||
|
visible = false
|
||||||
|
clip_contents = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
tooltip_text = "click on icon to copy its name to clipboard"
|
||||||
|
theme_override_fonts/normal_font = ExtResource("3_sggto")
|
||||||
|
theme_override_font_sizes/normal_font_size = 16
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = "Loading"
|
||||||
|
fit_content = true
|
||||||
|
scroll_active = false
|
||||||
|
autowrap_mode = 0
|
||||||
|
meta_underlined = false
|
||||||
|
threaded = true
|
||||||
|
script = ExtResource("3_hobrt")
|
||||||
|
icon_font = "Emojis"
|
||||||
|
size_slider = NodePath("../../../SliderContainer/HSlider")
|
||||||
|
search_line_edit = NodePath("../../../HBoxContainer/Search")
|
||||||
|
metadata/_tab_index = 1
|
|
@ -0,0 +1,13 @@
|
||||||
|
[gd_scene load_steps=3 format=3 uid="uid://qsslm1ensgyo"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://b0p1q2uqyvfmb" path="res://addons/icons-fonts/icon_finder/icon_finder_window.gd" id="1_nvv0t"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bni8w3a3pcbwn" path="res://addons/icons-fonts/icon_finder/IconFinder.tscn" id="2_aqufi"]
|
||||||
|
|
||||||
|
[node name="IconFinderWindow" type="Window"]
|
||||||
|
title = "Icon Finder"
|
||||||
|
initial_position = 2
|
||||||
|
size = Vector2i(775, 400)
|
||||||
|
wrap_controls = true
|
||||||
|
script = ExtResource("1_nvv0t")
|
||||||
|
|
||||||
|
[node name="IconFinder" parent="." instance=ExtResource("2_aqufi")]
|
|
@ -0,0 +1,82 @@
|
||||||
|
@tool
|
||||||
|
class_name IconsFontsRender
|
||||||
|
extends RichTextLabel
|
||||||
|
|
||||||
|
@export_enum("MaterialIcons", "Emojis")
|
||||||
|
var icon_font := "MaterialIcons"
|
||||||
|
|
||||||
|
@export var start_size := 1065
|
||||||
|
@export var size_slider: Slider
|
||||||
|
@export var search_line_edit : LineEdit
|
||||||
|
|
||||||
|
func set_icons_size(value:int):
|
||||||
|
IconsFonts.preview_size = value
|
||||||
|
set("theme_override_font_sizes/normal_font_size", value)
|
||||||
|
|
||||||
|
func get_font_data() -> Dictionary:
|
||||||
|
var data := {}
|
||||||
|
match icon_font:
|
||||||
|
"MaterialIcons": data = IconsFonts.material_icons
|
||||||
|
"Emojis": data = IconsFonts.emojis
|
||||||
|
_: text = "Unsupported IconsFont %s" % icon_font
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
func get_icon(key:String) -> String:
|
||||||
|
match icon_font:
|
||||||
|
"MaterialIcons": return IconsFonts.get_icon_char("MaterialIcons", key)
|
||||||
|
"Emojis": return str(IconsFonts.emojis[key])
|
||||||
|
|
||||||
|
return ""
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
visibility_changed.connect(_on_visibility_changed)
|
||||||
|
|
||||||
|
func _on_visibility_changed():
|
||||||
|
if visible:
|
||||||
|
set_icons_size(IconsFonts.preview_size)
|
||||||
|
update_table(search_line_edit.text)
|
||||||
|
|
||||||
|
func setup():
|
||||||
|
set_meta_underline(false)
|
||||||
|
set_icons_size(IconsFonts.preview_size)
|
||||||
|
|
||||||
|
func update_table(filter := ""):
|
||||||
|
var table = "[table={columns}, {inline_align}]"
|
||||||
|
var columns := int(size.x / IconsFonts.preview_size) + 1
|
||||||
|
if columns <= 10:
|
||||||
|
# size.x on start gives me 8 and slider.value is 16, so columns equals 1
|
||||||
|
# so I add new fallback var start_size = 1056,
|
||||||
|
# which is size.x after when it works
|
||||||
|
columns = int(start_size / IconsFonts.preview_size) + 1
|
||||||
|
|
||||||
|
table = table.format({
|
||||||
|
"columns": columns,
|
||||||
|
"inline_align": INLINE_ALIGNMENT_CENTER
|
||||||
|
})
|
||||||
|
|
||||||
|
var data := get_font_data()
|
||||||
|
if !data: return
|
||||||
|
|
||||||
|
var cells := columns
|
||||||
|
for key: String in data:
|
||||||
|
if filter and filter.to_lower() not in key: continue
|
||||||
|
cells -= 1
|
||||||
|
if cells <= 0: cells = columns
|
||||||
|
var link := "[url={link}]{icon}[/url]"
|
||||||
|
var icon := get_icon(key)
|
||||||
|
link = link.format({"link": key, "icon": icon})
|
||||||
|
|
||||||
|
var cell := "[cell]{link}[/cell]"
|
||||||
|
table += cell.format({"link": link})
|
||||||
|
|
||||||
|
cells = abs(cells)
|
||||||
|
while cells > columns:
|
||||||
|
cells -= 1
|
||||||
|
|
||||||
|
if cells > 0:
|
||||||
|
for c in cells:
|
||||||
|
table += "[cell] [/cell]"
|
||||||
|
|
||||||
|
table += "[/table]"
|
||||||
|
parse_bbcode(table)
|
|
@ -0,0 +1 @@
|
||||||
|
uid://8ujwc2fokr54
|
|
@ -0,0 +1,78 @@
|
||||||
|
@tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
@export var icons_renderers: Array[IconsFontsRender]
|
||||||
|
|
||||||
|
@export var tooltip := "click on icon to copy its name to clipboard"
|
||||||
|
|
||||||
|
@export
|
||||||
|
@onready var icons_renderers_tabs: TabContainer
|
||||||
|
|
||||||
|
@export
|
||||||
|
@onready var notify_label: Label
|
||||||
|
|
||||||
|
@export
|
||||||
|
@onready var search_line_edit: LineEdit
|
||||||
|
|
||||||
|
@export
|
||||||
|
@onready var size_slider: HSlider
|
||||||
|
|
||||||
|
@export
|
||||||
|
@onready var size_label: Label
|
||||||
|
|
||||||
|
@export
|
||||||
|
@onready var scroll_container: ScrollContainer
|
||||||
|
|
||||||
|
@export
|
||||||
|
@onready var fonts_dropdown: OptionButton
|
||||||
|
|
||||||
|
var icons_renderer: IconsFontsRender
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
notify_label.hide()
|
||||||
|
search_line_edit.text_changed.connect(update_table)
|
||||||
|
size_slider.value_changed.connect(update_icons_size)
|
||||||
|
fonts_dropdown.item_selected.connect(on_font_changed)
|
||||||
|
size_slider.value = IconsFonts.preview_size
|
||||||
|
|
||||||
|
for renderer: IconsFontsRender in icons_renderers:
|
||||||
|
renderer.tooltip_text = tooltip
|
||||||
|
|
||||||
|
func setup():
|
||||||
|
for renderer: IconsFontsRender in icons_renderers:
|
||||||
|
if !renderer.is_node_ready(): await ready
|
||||||
|
renderer.setup()
|
||||||
|
renderer.meta_clicked.connect(_on_meta)
|
||||||
|
icons_renderer = icons_renderers[0]
|
||||||
|
|
||||||
|
func update_icons_size(value: int):
|
||||||
|
size_label.text = str(value)
|
||||||
|
if icons_renderer:
|
||||||
|
icons_renderer.set_icons_size(value)
|
||||||
|
update_table(search_line_edit.text)
|
||||||
|
IconsFonts.preview_size = value
|
||||||
|
|
||||||
|
func on_font_changed(font_id: int):
|
||||||
|
icons_renderers_tabs.current_tab = font_id
|
||||||
|
icons_renderer = icons_renderers[font_id]
|
||||||
|
|
||||||
|
func update_table(filter := ""):
|
||||||
|
if not icons_renderer: return
|
||||||
|
icons_renderer.update_table(filter)
|
||||||
|
|
||||||
|
func _on_meta(link: String):
|
||||||
|
DisplayServer.clipboard_set(link)
|
||||||
|
notify_label.text = "Copied to Clipboard: " + link
|
||||||
|
notify_label.show()
|
||||||
|
|
||||||
|
var t := get_tree().create_tween()
|
||||||
|
t.tween_property(
|
||||||
|
notify_label, "modulate",
|
||||||
|
Color.GREEN, 1
|
||||||
|
)
|
||||||
|
t.chain().tween_property(
|
||||||
|
notify_label, "modulate",
|
||||||
|
Color.TRANSPARENT, 1
|
||||||
|
)
|
||||||
|
await t.finished
|
||||||
|
notify_label.hide()
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cq6lkta6wqfww
|
|
@ -0,0 +1,5 @@
|
||||||
|
@tool
|
||||||
|
extends Window
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
close_requested.connect(hide)
|
|
@ -0,0 +1 @@
|
||||||
|
uid://b0p1q2uqyvfmb
|
|
@ -0,0 +1,104 @@
|
||||||
|
@tool
|
||||||
|
# @singleton IconsFonts
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
const plugin_dir := "res://addons/icons-fonts/"
|
||||||
|
const icons_db := plugin_dir + "icons_fonts/IconsFonts.gd"
|
||||||
|
const inspector_plugin_path := plugin_dir + "inspector/font_icon_inspector.gd"
|
||||||
|
const sub_dir := "icon_finder/"
|
||||||
|
const icon_finder_dir := plugin_dir + sub_dir
|
||||||
|
const icon_finder_window_scene := icon_finder_dir + "IconFinderWindow.tscn"
|
||||||
|
const icon_finder_scene := icon_finder_dir + "IconFinder.tscn"
|
||||||
|
|
||||||
|
var command_palette := get_editor_interface().get_command_palette()
|
||||||
|
var editor_interface := get_editor_interface().get_base_control()
|
||||||
|
var icon_finder_window: Window
|
||||||
|
var icon_finder: Control
|
||||||
|
var popup_size := Vector2i(775, 400)
|
||||||
|
var inspector_plugin : EditorInspectorPlugin
|
||||||
|
|
||||||
|
var commands := [
|
||||||
|
[
|
||||||
|
"Icon Finder Window",
|
||||||
|
sub_dir + "icon_finder_window",
|
||||||
|
show_icon_finder_window
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Icon Finder Dock",
|
||||||
|
sub_dir + "icon_finder_dock",
|
||||||
|
add_to_dock
|
||||||
|
],
|
||||||
|
# todo uncomment when docs are ready!
|
||||||
|
# [
|
||||||
|
# "IconsFonts Help",
|
||||||
|
# sub_dir + "icon_help",
|
||||||
|
# help
|
||||||
|
# ],
|
||||||
|
]
|
||||||
|
|
||||||
|
var is_docked: bool
|
||||||
|
var icon_finder_loaded: PackedScene
|
||||||
|
var icon_finder_window_loaded: PackedScene
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
add_autoload_singleton("IconsFonts", icons_db)
|
||||||
|
# await IconsFonts.ready
|
||||||
|
|
||||||
|
icon_finder_loaded = load(icon_finder_scene)
|
||||||
|
icon_finder_window_loaded = load(icon_finder_window_scene)
|
||||||
|
|
||||||
|
is_docked = ProjectSettings.get_setting(
|
||||||
|
"application/addons/icon_finder/is_docked", true)
|
||||||
|
if is_docked: await add_to_dock()
|
||||||
|
|
||||||
|
for command: Array in commands:
|
||||||
|
add_tool_menu_item(command[0], command[2])
|
||||||
|
command_palette.add_command(command[0], command[1], command[2])
|
||||||
|
|
||||||
|
inspector_plugin = preload(inspector_plugin_path).new()
|
||||||
|
add_inspector_plugin(inspector_plugin)
|
||||||
|
|
||||||
|
func help():
|
||||||
|
# todo update when docs are ready!
|
||||||
|
# OS.shell_open("https://rakugoteam.github.io/material-icons-docs/")
|
||||||
|
pass
|
||||||
|
|
||||||
|
func add_to_dock():
|
||||||
|
if icon_finder_window:
|
||||||
|
editor_interface.remove_child.call_deferred(icon_finder_window)
|
||||||
|
|
||||||
|
await get_tree().create_timer(0.5).timeout
|
||||||
|
icon_finder = icon_finder_loaded.instantiate()
|
||||||
|
add_control_to_bottom_panel(icon_finder, "Icons Finder")
|
||||||
|
if !icon_finder.is_node_ready(): await ready
|
||||||
|
await icon_finder.setup()
|
||||||
|
|
||||||
|
func show_icon_finder_window():
|
||||||
|
if icon_finder:
|
||||||
|
remove_control_from_bottom_panel(icon_finder)
|
||||||
|
|
||||||
|
if !icon_finder_window:
|
||||||
|
icon_finder_window = icon_finder_window_loaded.instantiate()
|
||||||
|
editor_interface.add_child.call_deferred(icon_finder_window)
|
||||||
|
if !icon_finder_window.is_node_ready(): await ready
|
||||||
|
|
||||||
|
icon_finder_window.theme = editor_interface.theme
|
||||||
|
icon_finder_window.popup_centered(popup_size)
|
||||||
|
|
||||||
|
func _exit_tree():
|
||||||
|
if inspector_plugin:
|
||||||
|
remove_inspector_plugin(inspector_plugin)
|
||||||
|
|
||||||
|
for command: Array in commands:
|
||||||
|
remove_tool_menu_item(command[0])
|
||||||
|
command_palette.remove_command(command[0])
|
||||||
|
|
||||||
|
remove_autoload_singleton("IconsFonts")
|
||||||
|
|
||||||
|
if icon_finder:
|
||||||
|
remove_control_from_bottom_panel(icon_finder)
|
||||||
|
icon_finder.queue_free()
|
||||||
|
|
||||||
|
if icon_finder_window:
|
||||||
|
editor_interface.remove_child.call_deferred(icon_finder_window)
|
||||||
|
icon_finder_window.queue_free()
|
|
@ -0,0 +1 @@
|
||||||
|
uid://mihuo4o0cpte
|
|
@ -0,0 +1,172 @@
|
||||||
|
@tool
|
||||||
|
# @singleton IconsFonts
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
const docked_setting_path := "application/addons/icon_finder/is_docked"
|
||||||
|
const prev_size_setting_path := "application/addons/icon_finder/preview_size"
|
||||||
|
|
||||||
|
## Material Icons
|
||||||
|
const material_icons_json := "res://addons/icons-fonts/icons_fonts/MaterialIcons/icons.json"
|
||||||
|
const material_icons_font := "res://addons/icons-fonts/icons_fonts/MaterialIcons/material_design_icons.ttf"
|
||||||
|
|
||||||
|
## Emojis
|
||||||
|
const emojis_json := "res://addons/icons-fonts/icons_fonts/emojis/emojis.json"
|
||||||
|
const emojis_font := "res://addons/icons-fonts/icons_fonts/emojis/NotoColorEmoji.ttf"
|
||||||
|
|
||||||
|
signal font_loaded(font_name: String)
|
||||||
|
var material_icons := {}
|
||||||
|
var emojis := {}
|
||||||
|
|
||||||
|
static var is_docked: bool:
|
||||||
|
set(value):
|
||||||
|
ProjectSettings.set_setting(docked_setting_path, value)
|
||||||
|
get:
|
||||||
|
return ProjectSettings.get_setting(docked_setting_path, true)
|
||||||
|
|
||||||
|
static var preview_size: int:
|
||||||
|
set(value):
|
||||||
|
ProjectSettings.set_setting(prev_size_setting_path, value)
|
||||||
|
get:
|
||||||
|
return ProjectSettings.get_setting(prev_size_setting_path, 24)
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
var json: JSON
|
||||||
|
var content: String
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
json = load(material_icons_json)
|
||||||
|
init_material_icons_dict(json.data)
|
||||||
|
else:
|
||||||
|
json = JSON.new()
|
||||||
|
content = get_file_content(material_icons_json)
|
||||||
|
if json.parse(content) == OK:
|
||||||
|
init_material_icons_dict(json.data)
|
||||||
|
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
json = load(emojis_json)
|
||||||
|
init_emoji_dictionaries(json.data)
|
||||||
|
else:
|
||||||
|
json = JSON.new()
|
||||||
|
content = get_file_content(emojis_json)
|
||||||
|
if json.parse(content) == OK:
|
||||||
|
init_emoji_dictionaries(json.data)
|
||||||
|
|
||||||
|
func get_file_content(path: String) -> String:
|
||||||
|
var file := FileAccess.open(path, FileAccess.READ)
|
||||||
|
var content := ""
|
||||||
|
|
||||||
|
if file.get_error() == OK:
|
||||||
|
content = file.get_as_text()
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
return content
|
||||||
|
|
||||||
|
func init_material_icons_dict(data: Dictionary):
|
||||||
|
material_icons = data
|
||||||
|
for id in data:
|
||||||
|
var hex = material_icons[id]
|
||||||
|
material_icons[id] = ("0x" + hex).hex_to_int()
|
||||||
|
# prints(id, material_icons[id])
|
||||||
|
|
||||||
|
prints("FontsIcons: MaterialIcons loaded")
|
||||||
|
font_loaded.emit("MaterialIcons")
|
||||||
|
|
||||||
|
func init_emoji_dictionaries(dict: Dictionary):
|
||||||
|
for emoji in dict:
|
||||||
|
var keys = dict[emoji]
|
||||||
|
for key in keys:
|
||||||
|
emojis[key] = emoji
|
||||||
|
|
||||||
|
prints("FontsIcons: Emojis loaded")
|
||||||
|
font_loaded.emit("Emojis")
|
||||||
|
|
||||||
|
func get_icon_code(font: String, id: String) -> int:
|
||||||
|
if "," in id:
|
||||||
|
id = id.split(",")[0]
|
||||||
|
|
||||||
|
match font:
|
||||||
|
"MaterialIcons":
|
||||||
|
if id in material_icons:
|
||||||
|
return material_icons[id]
|
||||||
|
|
||||||
|
push_warning("Icon '%s' in font %s not found." % [id, font])
|
||||||
|
return 0
|
||||||
|
|
||||||
|
func get_emoji_unicode(id: String) -> String:
|
||||||
|
if id in emojis:
|
||||||
|
# prints(id, emojis[id])
|
||||||
|
return emojis[id]
|
||||||
|
|
||||||
|
push_warning("Emoji %s not found." % id)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
func get_icon_char(font: String, id: String) -> String:
|
||||||
|
match font:
|
||||||
|
"MaterialIcons":
|
||||||
|
return char(get_icon_code(font, id))
|
||||||
|
|
||||||
|
"Emojis":
|
||||||
|
return get_emoji_unicode(id)
|
||||||
|
|
||||||
|
return ""
|
||||||
|
|
||||||
|
## will parse text using:
|
||||||
|
## - parse_material_icons()
|
||||||
|
## - parse_emojis()
|
||||||
|
## - parse_game_icons()
|
||||||
|
func parse_text(text: String) -> String:
|
||||||
|
text = parse_material_icons(text)
|
||||||
|
text = parse_emojis(text)
|
||||||
|
# todo add game-icons parse
|
||||||
|
return text
|
||||||
|
|
||||||
|
## will replace [mi:icon_name] with [font=MaterialIcons]icon_char[/font]
|
||||||
|
func parse_material_icons(text: String) -> String:
|
||||||
|
var regex = RegEx.new()
|
||||||
|
regex.compile("\\[mi:(.*?)\\]")
|
||||||
|
var x = regex.search(text)
|
||||||
|
while x != null:
|
||||||
|
var icon = x.get_string(1)
|
||||||
|
var char = get_icon_char("MaterialIcons", icon)
|
||||||
|
var r = "[font={font}]{char}[/font]"
|
||||||
|
r = r.format({"font": material_icons_font, "char": char})
|
||||||
|
|
||||||
|
if icon.split(",").size() > 1:
|
||||||
|
var size = icon.split(",")[1]
|
||||||
|
var s = "[font_size={size}]{r}[/font_size]"
|
||||||
|
r = s.format({"size": size, "r": r})
|
||||||
|
|
||||||
|
text = text.replace(x.get_string(), r)
|
||||||
|
x = regex.search(text)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
func get_emoji_bbcode(id: String, size := 0) -> String:
|
||||||
|
var emoji := get_icon_char("Emojis", id)
|
||||||
|
if !emoji: return ""
|
||||||
|
|
||||||
|
var bbcode := "[font=%s]%s[/font]" % [emojis_font, emoji]
|
||||||
|
if size <= 0: return bbcode
|
||||||
|
|
||||||
|
return "[font_size=%s]%s[/font_size]" % [size, bbcode]
|
||||||
|
|
||||||
|
## will replace :emoji_name: with [font=Emojis]emoji_char[/font]
|
||||||
|
func parse_emojis(text: String):
|
||||||
|
var re = RegEx.new()
|
||||||
|
re.compile(":[\\w\\d]+(,\\s*\\d+)?:")
|
||||||
|
var result = re.search(text)
|
||||||
|
while result != null:
|
||||||
|
var temp := result.get_string()
|
||||||
|
temp = temp.replace(":", "")
|
||||||
|
var emoji := temp
|
||||||
|
var size := 0
|
||||||
|
|
||||||
|
if "," in temp:
|
||||||
|
var splited := temp.split(",")
|
||||||
|
emoji = splited[0]
|
||||||
|
size = int(splited[1].replace(" ", ""))
|
||||||
|
|
||||||
|
var replacement := get_emoji_bbcode(emoji, size)
|
||||||
|
text = text.replace(result.get_string(), replacement)
|
||||||
|
result = re.search(text)
|
||||||
|
|
||||||
|
return text
|
|
@ -0,0 +1 @@
|
||||||
|
uid://be1kqgxxr4eyy
|
|
@ -0,0 +1,20 @@
|
||||||
|
Pictogrammers Free License
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
This icon collection is released as free, open source, and GPL friendly by
|
||||||
|
the [Pictogrammers](http://pictogrammers.com/) icon group. You may use it
|
||||||
|
for commercial projects, open source projects, or anything really.
|
||||||
|
|
||||||
|
# Icons: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
Some of the icons are redistributed under the Apache 2.0 license. All other
|
||||||
|
icons are either redistributed under their respective licenses or are
|
||||||
|
distributed under the Apache 2.0 license.
|
||||||
|
|
||||||
|
# Fonts: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
All web and desktop fonts are distributed under the Apache 2.0 license. Web
|
||||||
|
and desktop fonts contain some icons that are redistributed under the Apache
|
||||||
|
2.0 license. All other icons are either redistributed under their respective
|
||||||
|
licenses or are distributed under the Apache 2.0 license.
|
||||||
|
|
||||||
|
# Code: MIT (https://opensource.org/licenses/MIT)
|
||||||
|
The MIT license applies to all non-font and non-icon files.
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="font_data_dynamic"
|
||||||
|
type="FontFile"
|
||||||
|
uid="uid://bbfeoo2kuf30n"
|
||||||
|
path="res://.godot/imported/material_design_icons.ttf-2d3d78b67944bff81f1808ffd996cd10.fontdata"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/icons-fonts/icons_fonts/MaterialIcons/material_design_icons.ttf"
|
||||||
|
dest_files=["res://.godot/imported/material_design_icons.ttf-2d3d78b67944bff81f1808ffd996cd10.fontdata"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
Rendering=null
|
||||||
|
antialiasing=1
|
||||||
|
generate_mipmaps=false
|
||||||
|
disable_embedded_bitmaps=true
|
||||||
|
multichannel_signed_distance_field=false
|
||||||
|
msdf_pixel_range=8
|
||||||
|
msdf_size=48
|
||||||
|
allow_system_fallback=true
|
||||||
|
force_autohinter=false
|
||||||
|
hinting=1
|
||||||
|
subpixel_positioning=1
|
||||||
|
keep_rounding_remainders=true
|
||||||
|
oversampling=0.0
|
||||||
|
Fallbacks=null
|
||||||
|
fallbacks=[]
|
||||||
|
Compress=null
|
||||||
|
compress=true
|
||||||
|
preload=[]
|
||||||
|
language_support={}
|
||||||
|
script_support={}
|
||||||
|
opentype_features={}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
||||||
|
import re, json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# URLs of the files to download
|
||||||
|
css_url = "https://github.com/Templarian/MaterialDesign-Webfont/raw/master/css/materialdesignicons.css"
|
||||||
|
ttf_url = "https://github.com/Templarian/MaterialDesign-Webfont/raw/master/fonts/materialdesignicons-webfont.ttf"
|
||||||
|
|
||||||
|
# Function to download a file given its URL and save it with a specified name
|
||||||
|
def download_file(url, file_name):
|
||||||
|
response = requests.get(url)
|
||||||
|
with open(file_name, 'wb') as file:
|
||||||
|
file.write(response.content)
|
||||||
|
|
||||||
|
# Download the CSS file
|
||||||
|
download_file(css_url, 'materialdesignicons.css')
|
||||||
|
print("CSS file downloaded.")
|
||||||
|
|
||||||
|
# Download the TTF font file
|
||||||
|
download_file(ttf_url, 'material_design_icons.ttf')
|
||||||
|
print("TTF font file downloaded.")
|
||||||
|
|
||||||
|
# Specify the path to your text file
|
||||||
|
file_path = 'materialdesignicons.css'
|
||||||
|
|
||||||
|
# Open the file in read mode
|
||||||
|
with open(file_path, 'r') as file:
|
||||||
|
# Read the entire file content as a single string
|
||||||
|
file_content = file.read()
|
||||||
|
|
||||||
|
# Define your regex pattern
|
||||||
|
pattern = re.compile(r'\.mdi-([a-zA-Z0-9-]+)::before \{\n\s+.*?content: "([^"]*)";\n\}',
|
||||||
|
re.DOTALL
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find all matches using the regex pattern
|
||||||
|
matches = re.findall(pattern, file_content)
|
||||||
|
|
||||||
|
# Create an empty dictionary to store the results
|
||||||
|
icons_dict = {}
|
||||||
|
|
||||||
|
# Now, 'matches' contains a list of tuples where each tuple contains the matched parts
|
||||||
|
for match in matches:
|
||||||
|
mdi_class, content_hex = match
|
||||||
|
content_unicode = content_hex.replace("\\", "")
|
||||||
|
icons_dict[mdi_class] = content_unicode
|
||||||
|
print(f"icon: {mdi_class}, unicode: {content_unicode}")
|
||||||
|
|
||||||
|
# Save the dictionary to a JSON file
|
||||||
|
with open('icons.json', 'w') as json_file:
|
||||||
|
json.dump(icons_dict, json_file, indent=2)
|
||||||
|
|
||||||
|
print("Icons saved to 'icons.json'")
|
Binary file not shown.
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="font_data_dynamic"
|
||||||
|
type="FontFile"
|
||||||
|
uid="uid://be10y8fgoiayy"
|
||||||
|
path="res://.godot/imported/NotoColorEmoji.ttf-7420805f2f15fd3d077a2cb64d7e2acd.fontdata"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/icons-fonts/icons_fonts/emojis/NotoColorEmoji.ttf"
|
||||||
|
dest_files=["res://.godot/imported/NotoColorEmoji.ttf-7420805f2f15fd3d077a2cb64d7e2acd.fontdata"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
Rendering=null
|
||||||
|
antialiasing=1
|
||||||
|
generate_mipmaps=false
|
||||||
|
disable_embedded_bitmaps=true
|
||||||
|
multichannel_signed_distance_field=false
|
||||||
|
msdf_pixel_range=8
|
||||||
|
msdf_size=48
|
||||||
|
allow_system_fallback=true
|
||||||
|
force_autohinter=false
|
||||||
|
hinting=1
|
||||||
|
subpixel_positioning=1
|
||||||
|
keep_rounding_remainders=true
|
||||||
|
oversampling=0.0
|
||||||
|
Fallbacks=null
|
||||||
|
fallbacks=[]
|
||||||
|
Compress=null
|
||||||
|
compress=true
|
||||||
|
preload=[]
|
||||||
|
language_support={}
|
||||||
|
script_support={}
|
||||||
|
opentype_features={}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,483 @@
|
||||||
|
"""
|
||||||
|
Base on https://github.com/carpedm20/emoji/blob/master/utils/get_codes_from_unicode_emoji_data_files.py
|
||||||
|
Extract the full list of emoji and names from the Unicode emoji data files
|
||||||
|
https://unicode.org/Public/emoji/{v}/emoji-test.txt and
|
||||||
|
https://www.unicode.org/Public/{v}/ucd/emoji/emoji-variation-sequences.txt
|
||||||
|
and apply as much formatting as possible so the codes can be dropped into the
|
||||||
|
emoji registry file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
import re, bs4
|
||||||
|
import unicodedata
|
||||||
|
import requests
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import logging
|
||||||
|
import emoji as emoji_pkg
|
||||||
|
import json
|
||||||
|
|
||||||
|
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
||||||
|
|
||||||
|
def get_text_from_url(url: str) -> str:
|
||||||
|
"""Get text from url"""
|
||||||
|
|
||||||
|
return requests.get(url).text
|
||||||
|
|
||||||
|
def get_emoji_from_url(version: float) -> list:
|
||||||
|
"""Get splitlines of emojis list from unicode.org"""
|
||||||
|
|
||||||
|
url = f"https://unicode.org/Public/emoji/{version}/emoji-test.txt"
|
||||||
|
return get_text_from_url(url).splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
def get_emoji_variation_sequence_from_url(version: str) -> list:
|
||||||
|
"""Get splitlines of emoji variation sequences from unicode.org"""
|
||||||
|
|
||||||
|
url = f"https://www.unicode.org/Public/{version}/ucd/emoji/emoji-variation-sequences.txt"
|
||||||
|
return get_text_from_url(url).splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
def get_emojiterra_from_url(url: str) -> dict:
|
||||||
|
html = get_text_from_url(url)
|
||||||
|
|
||||||
|
soup = bs4.BeautifulSoup(html, "html.parser")
|
||||||
|
emojis = {}
|
||||||
|
|
||||||
|
data = soup.find_all('li')
|
||||||
|
data = [i for i in data if 'href' not in i.attrs and 'data-e' in i.attrs and i['data-e'].strip()]
|
||||||
|
|
||||||
|
for i in data:
|
||||||
|
code = i['data-e']
|
||||||
|
emojis[code] = i['title'].strip()
|
||||||
|
|
||||||
|
assert len(data) > 100, f"emojiterra data from {url} has only {len(data)} entries"
|
||||||
|
|
||||||
|
return emojis
|
||||||
|
|
||||||
|
|
||||||
|
def get_cheat_sheet(url: str) -> dict:
|
||||||
|
"""
|
||||||
|
Returns a dict of emoji to short-names:
|
||||||
|
E.g. {'👴': ':old_man:', '👵': ':old_woman:', ... }
|
||||||
|
"""
|
||||||
|
|
||||||
|
html = get_text_from_url(url)
|
||||||
|
|
||||||
|
soup = bs4.BeautifulSoup(html, "html.parser")
|
||||||
|
emojis = {}
|
||||||
|
|
||||||
|
items = soup.find(class_='ecs-list').find_all(class_='_item')
|
||||||
|
|
||||||
|
pattern = re.compile(r'U\+([0-9A-F]+)')
|
||||||
|
|
||||||
|
for i in items:
|
||||||
|
unicode_text = i.find(class_='unicode').text
|
||||||
|
|
||||||
|
code_points = pattern.findall(unicode_text)
|
||||||
|
code = ''.join(chr(int(x,16)) for x in code_points)
|
||||||
|
|
||||||
|
emojis[code] = i.find(class_='shortcode').text
|
||||||
|
|
||||||
|
# Remove some unwanted and some weird entries from the cheat sheet
|
||||||
|
filtered = {}
|
||||||
|
for emj, short_code in emojis.items():
|
||||||
|
|
||||||
|
if short_code.startswith(':flag_'):
|
||||||
|
# Skip flags from cheat-sheet, because we already have very similar aliases for the flags
|
||||||
|
continue
|
||||||
|
|
||||||
|
if '⊛' in short_code:
|
||||||
|
# Strange emoji with ⊛ in the short-code
|
||||||
|
continue
|
||||||
|
|
||||||
|
if emj == '\U0001F93E\U0000200D\U00002640\U0000FE0F':
|
||||||
|
# The short-code for this emoji is wrong
|
||||||
|
continue
|
||||||
|
|
||||||
|
if emj == '\U0001F468\U0000200D\U0001F468\U0000200D\U0001F467':
|
||||||
|
# The short-code for this emoji is wrong
|
||||||
|
continue
|
||||||
|
|
||||||
|
if short_code.startswith('::'):
|
||||||
|
# Do not allow short-codes to have double :: at the start
|
||||||
|
short_code = short_code[1:]
|
||||||
|
|
||||||
|
if short_code.endswith('::'):
|
||||||
|
# Do not allow short-codes to have double :: at the end
|
||||||
|
short_code = short_code[:-1]
|
||||||
|
|
||||||
|
filtered[emj] = short_code
|
||||||
|
|
||||||
|
assert len(filtered) > 100, f"emoji-cheat-sheet data from {url} has only {len(filtered)} entries"
|
||||||
|
|
||||||
|
return filtered
|
||||||
|
|
||||||
|
def get_emoji_from_youtube(url: str) -> dict:
|
||||||
|
"""Get emoji alias from Youtube
|
||||||
|
Returns a dict of emoji to list of short-names:
|
||||||
|
E.g. {'💁': [':person_tipping_hand:', ':information_desk_person:'], '😉': [':winking_face:', ':wink:']}
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = requests.get(url).json()
|
||||||
|
|
||||||
|
output = {}
|
||||||
|
for obj in data:
|
||||||
|
if 'shortcuts' not in obj or 'emojiId' not in obj:
|
||||||
|
continue
|
||||||
|
|
||||||
|
shortcuts = [x for x in obj['shortcuts'] if x.startswith(':') and x.endswith(':')]
|
||||||
|
|
||||||
|
if shortcuts:
|
||||||
|
output[obj['emojiId']] = shortcuts
|
||||||
|
|
||||||
|
assert len(output) > 100, f"youtube data from {url} has only {len(output)} entries"
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def extract_emojis(emojis_lines: list, sequences_lines: list) -> dict:
|
||||||
|
"""Extract emojis line by line to dict"""
|
||||||
|
|
||||||
|
output = {}
|
||||||
|
for line in emojis_lines:
|
||||||
|
if not line == "" and not line.startswith("#"):
|
||||||
|
emoji_status = line.split(";")[1].strip().split(" ")[0]
|
||||||
|
|
||||||
|
codes = line.split(";")[0].strip().split(" ")
|
||||||
|
separated_line = line.split(" # ")[-1].strip().split(" ")
|
||||||
|
separated_name = separated_line[2:]
|
||||||
|
version_str = separated_line[1]
|
||||||
|
emoji_name = (
|
||||||
|
"_".join(separated_name)
|
||||||
|
.removeprefix("flag:_")
|
||||||
|
.replace(":", "")
|
||||||
|
.replace(",", "")
|
||||||
|
.replace("\u201c", "")
|
||||||
|
.replace("\u201d", "")
|
||||||
|
.replace("\u229b", "")
|
||||||
|
.strip()
|
||||||
|
.replace(" ", "_")
|
||||||
|
.replace("_-_", "-")
|
||||||
|
)
|
||||||
|
|
||||||
|
emoji_code = "".join(
|
||||||
|
[
|
||||||
|
"\\U0000" + code if len(code) == 4 else "\\U000" + code
|
||||||
|
for code in codes
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
version = float(version_str.replace("E", "").strip())
|
||||||
|
|
||||||
|
if emoji_code in output:
|
||||||
|
raise Exception("Duplicate emoji: " +
|
||||||
|
emoji_name + " " + emoji_code)
|
||||||
|
|
||||||
|
output[emoji_code] = {
|
||||||
|
"en": emoji_name,
|
||||||
|
"status": emoji_status.replace("-", "_"),
|
||||||
|
"version": version
|
||||||
|
}
|
||||||
|
|
||||||
|
# Walk through the emoji-variation-sequences.txt
|
||||||
|
for line in sequences_lines:
|
||||||
|
if not line == "" and not line.startswith("#"):
|
||||||
|
# No variant
|
||||||
|
normal_codes = line.split(";")[0].strip().split(" ")
|
||||||
|
normal_code = "".join(
|
||||||
|
[
|
||||||
|
"\\U0000" + code if len(code) == 4 else "\\U000" + code
|
||||||
|
for code in normal_codes
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if normal_code in output:
|
||||||
|
output[normal_code]["variant"] = True
|
||||||
|
|
||||||
|
# Text variant U+FE0E
|
||||||
|
text_codes = re.sub(r'\s*FE0E\s*$', '',
|
||||||
|
line.split(";")[0]).strip().split(" ")
|
||||||
|
text_code = "".join(
|
||||||
|
[
|
||||||
|
"\\U0000" + code if len(code) == 4 else "\\U000" + code
|
||||||
|
for code in text_codes
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if text_code in output:
|
||||||
|
output[text_code]["variant"] = True
|
||||||
|
|
||||||
|
# Emoji variant U+FE0F
|
||||||
|
emoji_codes = re.sub(r'\s*FE0F\s*$', '', line.split(";")[0]).strip().split(" ")
|
||||||
|
emoji_code = "".join(
|
||||||
|
[
|
||||||
|
"\\U0000" + code if len(code) == 4 else "\\U000" + code
|
||||||
|
for code in emoji_codes
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if emoji_code in output:
|
||||||
|
output[emoji_code]["variant"] = True
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def adapt_emoji_name(text: str, lang: str, emj: str) -> str:
|
||||||
|
# Use NFKC-form (single character instead of character + diacritic)
|
||||||
|
# Unicode.org files should be formatted like this anyway, but emojiterra is not consistent
|
||||||
|
text = unicodedata.normalize('NFKC', text)
|
||||||
|
|
||||||
|
# Remove white space
|
||||||
|
text = "_".join(text.split(" "))
|
||||||
|
|
||||||
|
emoji_name = ":" + (
|
||||||
|
text
|
||||||
|
.lower()
|
||||||
|
.removeprefix("flag:_")
|
||||||
|
.replace(":", "")
|
||||||
|
.replace(",", "")
|
||||||
|
.replace('"', "")
|
||||||
|
.replace("\u201e", "")
|
||||||
|
.replace("\u201f", "")
|
||||||
|
.replace("\u202f", "")
|
||||||
|
.replace("\u229b", "")
|
||||||
|
.replace("\u2013", "-")
|
||||||
|
.replace(",_", ",")
|
||||||
|
.strip()
|
||||||
|
.replace(" ", "_")
|
||||||
|
.replace("_-_", "-")
|
||||||
|
) + ":"
|
||||||
|
|
||||||
|
emoji_name = (emoji_name
|
||||||
|
.replace("____", "_")
|
||||||
|
.replace("___", "_")
|
||||||
|
.replace("__", "_")
|
||||||
|
.replace("--", "-"))
|
||||||
|
|
||||||
|
return emoji_name
|
||||||
|
|
||||||
|
def add_unicode_annotations(data, lang, url):
|
||||||
|
xml = get_text_from_url(url)
|
||||||
|
|
||||||
|
tree = ET.fromstring(xml)
|
||||||
|
annotations = tree.find('annotations')
|
||||||
|
for annotation in annotations:
|
||||||
|
if annotation.get('type') == 'tts':
|
||||||
|
emj = annotation.get('cp')
|
||||||
|
text = annotation.text.strip()
|
||||||
|
|
||||||
|
emoji_name = adapt_emoji_name(text, lang, emj)
|
||||||
|
|
||||||
|
if emj in data and data[emj] != emoji_name:
|
||||||
|
print(
|
||||||
|
f"# {lang}: CHANGED {data[emj]} TO {emoji_name} \t\t(Original: {text})")
|
||||||
|
data[emj] = emoji_name
|
||||||
|
|
||||||
|
def extract_names(github_tag, github_lang, lang, emoji_terra={}):
|
||||||
|
"""Copies emoji.EMOJI_DATA[emj][lang] and adds the names from the Unicode CLDR xml
|
||||||
|
|
||||||
|
Find latest tag at https://cldr.unicode.org/index/downloads or
|
||||||
|
https://github.com/unicode-org/cldr/tree/main/common/annotations
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = get_UNICODE_EMOJI(lang)
|
||||||
|
add_unicode_annotations(data, lang, f"https://github.com/unicode-org/cldr/raw/{github_tag}/common/annotations/{github_lang}.xml")
|
||||||
|
add_unicode_annotations(data, lang, f"https://github.com/unicode-org/cldr/raw/{github_tag}/common/annotationsDerived/{github_lang}.xml")
|
||||||
|
|
||||||
|
# Add names from emojiterra if there is no unicode annotation
|
||||||
|
for emj, name in emoji_terra.items():
|
||||||
|
if emj in emoji_pkg.EMOJI_DATA and emj not in data:
|
||||||
|
emoji_name = adapt_emoji_name(name, lang, emj)
|
||||||
|
data[emj] = emoji_name
|
||||||
|
|
||||||
|
# There are some emoji with two code sequences for the same emoji, one that ends with \uFE0F and one that does not.
|
||||||
|
# The one that ends with \uFE0F is the "new" emoji, that is RGI.
|
||||||
|
# The Unicode translation data sometimes only has one of the two code sequences and is missing the other one.
|
||||||
|
# In that case we want to use the existing translation for both code sequences.
|
||||||
|
missing_translation = {}
|
||||||
|
for emj in data:
|
||||||
|
if emj.endswith('\uFE0F') and emj[0:-1] not in data and emj[0:-1] in emoji_pkg.EMOJI_DATA:
|
||||||
|
# the emoji NOT ending in \uFE0F exists in EMOJI_DATA but is has no translation
|
||||||
|
# e.g. ':pirate_flag:' -> '\U0001F3F4\u200D\u2620\uFE0F' or '\U0001F3F4\u200D\u2620'
|
||||||
|
missing_translation[emj[0:-1]] = data[emj]
|
||||||
|
|
||||||
|
with_emoji_type = f"{emj}\uFE0F"
|
||||||
|
if not emj.endswith('\uFE0F') and with_emoji_type not in data and with_emoji_type in emoji_pkg.EMOJI_DATA:
|
||||||
|
# the emoji ending in \uFE0F exists in EMOJI_DATA but is has no translation
|
||||||
|
# e.g. ':face_in_clouds:' -> '\U0001F636\u200D\U0001F32B\uFE0F' or '\U0001F636\u200D\U0001F32B'
|
||||||
|
missing_translation[with_emoji_type] = data[emj]
|
||||||
|
|
||||||
|
# Find emoji that contain \uFE0F inside the sequence (not just as a suffix)
|
||||||
|
# e.g. ':eye_in_speech_bubble:' -> '\U0001F441\uFE0F\u200D\U0001F5E8\uFE0F'
|
||||||
|
for emj in emoji_pkg.EMOJI_DATA:
|
||||||
|
if emj in data:
|
||||||
|
continue
|
||||||
|
emj_no_variant = emj.replace('\uFE0F', '')
|
||||||
|
if emj_no_variant != emj and emj_no_variant in data:
|
||||||
|
# the emoji with \uFE0F has no translation, but the emoji without all \uFE0F has a translation
|
||||||
|
data[emj] = data[emj_no_variant]
|
||||||
|
|
||||||
|
data.update(missing_translation)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_emoji_from_github_api(url: str) -> dict:
|
||||||
|
"""Get emoji alias from GitHub API
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = requests.get(url).json()
|
||||||
|
pattern = re.compile(r"unicode/([0-9a-fA-F-]+)\.[a-z]+")
|
||||||
|
|
||||||
|
output = {}
|
||||||
|
for name, img in data.items():
|
||||||
|
m = pattern.search(img)
|
||||||
|
if m:
|
||||||
|
emj = "".join(chr(int(h, 16)) for h in m.group(1).split('-'))
|
||||||
|
output[name] = emj
|
||||||
|
else:
|
||||||
|
pass # Special GitHub emoji that is not part of Unicode
|
||||||
|
|
||||||
|
assert len(output) > 100, f"data from github API has only {len(output)} entries"
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
GITHUB_REMOVED_CHARS = re.compile("\u200D|\uFE0F|\uFE0E", re.IGNORECASE)
|
||||||
|
|
||||||
|
def find_github_aliases(emj, github_dict, v, emj_no_variant=None):
|
||||||
|
aliases = set()
|
||||||
|
|
||||||
|
# Strip ZWJ \u200D, text_type \uFE0E and emoji_type \uFE0F
|
||||||
|
# because the GitHub API does not include these
|
||||||
|
emj_clean = GITHUB_REMOVED_CHARS.sub("", emj)
|
||||||
|
|
||||||
|
for gh_alias in github_dict:
|
||||||
|
if emj == github_dict[gh_alias]:
|
||||||
|
aliases.add(gh_alias)
|
||||||
|
elif 'variant' in v and emj_no_variant == github_dict[gh_alias]:
|
||||||
|
aliases.add(gh_alias)
|
||||||
|
elif emj_clean == github_dict[gh_alias]:
|
||||||
|
aliases.add(gh_alias)
|
||||||
|
|
||||||
|
return aliases
|
||||||
|
|
||||||
|
def ascii(s):
|
||||||
|
# return escaped Code points \U000AB123
|
||||||
|
return s.encode("unicode-escape").decode()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.info(' Downloading...\n')
|
||||||
|
|
||||||
|
# Find the latest version at https://www.unicode.org/reports/tr51/#emoji_data
|
||||||
|
emoji_source = get_emoji_from_url(15.1)
|
||||||
|
emoji_sequences_source = get_emoji_variation_sequence_from_url('15.1.0')
|
||||||
|
emojis = extract_emojis(emoji_source, emoji_sequences_source)
|
||||||
|
# Find latest release tag at https://cldr.unicode.org/index/downloads
|
||||||
|
github_tag = 'release-44-1'
|
||||||
|
|
||||||
|
languages = {}
|
||||||
|
|
||||||
|
github_alias_dict = get_emoji_from_github_api('https://api.github.com/emojis')
|
||||||
|
cheat_sheet_dict = get_cheat_sheet('https://www.webfx.com/tools/emoji-cheat-sheet/')
|
||||||
|
youtube_dict = get_emoji_from_youtube('https://www.gstatic.com/youtube/img/emojis/emojis-png-7.json')
|
||||||
|
|
||||||
|
logging.info(' Combining...\n')
|
||||||
|
|
||||||
|
used_github_aliases = set()
|
||||||
|
|
||||||
|
escapedToUnicodeMap = {escaped: escaped.encode().decode('unicode-escape') for escaped in emojis} # maps: "\\U0001F4A4" to "\U0001F4A4"
|
||||||
|
|
||||||
|
all_existing_aliases_and_en = set(item for emj_data in emoji_pkg.EMOJI_DATA.values() for item in emj_data.get('alias', []))
|
||||||
|
all_existing_aliases_and_en.update(emj_data['en'] for emj_data in emoji_pkg.EMOJI_DATA.values())
|
||||||
|
|
||||||
|
f = 0
|
||||||
|
c = 0
|
||||||
|
new_aliases = []
|
||||||
|
emojis_data = {}
|
||||||
|
logging.info(' Print EMOJI_DATA...\n')
|
||||||
|
for code, v in sorted(emojis.items(), key=lambda item: item[1]["en"]):
|
||||||
|
language_str = ''
|
||||||
|
emj = escapedToUnicodeMap[code]
|
||||||
|
|
||||||
|
alternative = re.sub(r"\\U0000FE0[EF]$", "", code)
|
||||||
|
emj_no_variant = escapedToUnicodeMap[alternative]
|
||||||
|
|
||||||
|
# add names in other languages
|
||||||
|
for lang in languages:
|
||||||
|
if emj in languages[lang]:
|
||||||
|
language_str += ",\n '%s': '%s'" % (
|
||||||
|
lang, languages[lang][emj])
|
||||||
|
elif 'variant' in v:
|
||||||
|
# the language annotation uses the normal emoji (no variant), while the emoji-test.txt uses the emoji or text variant
|
||||||
|
if emj_no_variant in languages[lang]:
|
||||||
|
language_str += ",\n '%s': '%s'" % (
|
||||||
|
lang, languages[lang][emj_no_variant])
|
||||||
|
|
||||||
|
# Add existing alias from EMOJI_DATA
|
||||||
|
aliases = set()
|
||||||
|
if emj in emoji_pkg.EMOJI_DATA and 'alias' in emoji_pkg.EMOJI_DATA[emj]:
|
||||||
|
aliases.update(a[1:-1] for a in emoji_pkg.EMOJI_DATA[emj]['alias'])
|
||||||
|
old_aliases = set(aliases)
|
||||||
|
|
||||||
|
if emj_no_variant in emoji_pkg.EMOJI_DATA and 'alias' in emoji_pkg.EMOJI_DATA[emj_no_variant]:
|
||||||
|
aliases.update(a[1:-1] for a in emoji_pkg.EMOJI_DATA[emj_no_variant]['alias'])
|
||||||
|
|
||||||
|
# Add alias from GitHub API
|
||||||
|
github_aliases = find_github_aliases(emj, github_alias_dict, v, emj_no_variant)
|
||||||
|
aliases.update(shortcut for shortcut in github_aliases if shortcut not in all_existing_aliases_and_en)
|
||||||
|
used_github_aliases.update(github_aliases)
|
||||||
|
|
||||||
|
# Add alias from cheat sheet
|
||||||
|
if emj in cheat_sheet_dict and cheat_sheet_dict[emj] not in all_existing_aliases_and_en:
|
||||||
|
aliases.add(cheat_sheet_dict[emj][1:-1])
|
||||||
|
if emj_no_variant in cheat_sheet_dict and cheat_sheet_dict[emj_no_variant] not in all_existing_aliases_and_en:
|
||||||
|
aliases.add(cheat_sheet_dict[emj_no_variant][1:-1])
|
||||||
|
|
||||||
|
# Add alias from youtube
|
||||||
|
if emj in youtube_dict:
|
||||||
|
aliases.update(shortcut[1:-1] for shortcut in youtube_dict[emj] if shortcut not in all_existing_aliases_and_en)
|
||||||
|
if emj_no_variant in youtube_dict:
|
||||||
|
aliases.update(shortcut[1:-1] for shortcut in youtube_dict[emj_no_variant] if shortcut not in all_existing_aliases_and_en)
|
||||||
|
|
||||||
|
# Remove if alias is same as 'en'-name
|
||||||
|
if v["en"] in aliases:
|
||||||
|
aliases.remove(v["en"])
|
||||||
|
|
||||||
|
# Store new aliases to print them at the end after the dict of dicts
|
||||||
|
if emj in emoji_pkg.EMOJI_DATA:
|
||||||
|
if 'alias' in emoji_pkg.EMOJI_DATA[emj]:
|
||||||
|
diff = aliases.difference(a[1:-1] for a in emoji_pkg.EMOJI_DATA[emj]['alias'])
|
||||||
|
else:
|
||||||
|
diff = aliases
|
||||||
|
for a in diff:
|
||||||
|
new_aliases.append(f"# alias NEW {a} FOR {emj} CODE {code}")
|
||||||
|
|
||||||
|
# Keep the order of existing aliases intact
|
||||||
|
if emj in emoji_pkg.EMOJI_DATA and 'alias' in emoji_pkg.EMOJI_DATA[emj]:
|
||||||
|
aliases = [a[1:-1] for a in emoji_pkg.EMOJI_DATA[emj]['alias']] + [a for a in aliases if f":{a}:" not in emoji_pkg.EMOJI_DATA[emj]['alias']]
|
||||||
|
|
||||||
|
if any("flag_for_" in a for a in aliases):
|
||||||
|
# Put the :flag_for_COUNTRY: alias as the first entry so that it gets picked by demojize()
|
||||||
|
# This ensures compatibility because in the past there was only the :flag_for_COUNTRY: alias
|
||||||
|
aliases = [a for a in aliases if "flag_for_" in a]
|
||||||
|
aliases += [a for a in aliases if "flag_for_" not in a]
|
||||||
|
|
||||||
|
# emoji to dict
|
||||||
|
emojis_data[emj] = [v["en"].lower()]
|
||||||
|
|
||||||
|
for a in aliases:
|
||||||
|
emojis_data[emj].append(a)
|
||||||
|
|
||||||
|
if v["status"] == "fully_qualified":
|
||||||
|
f += 1
|
||||||
|
elif v["status"] == "component":
|
||||||
|
c += 1
|
||||||
|
|
||||||
|
with open("emojis.json", "w") as outfile:
|
||||||
|
json.dump(emojis_data, outfile, sort_keys=True, indent=2)
|
||||||
|
|
||||||
|
logging.debug(f" # Total count of emojis: {len(emojis)}")
|
||||||
|
logging.debug(f" # fully_qualified: {f}")
|
||||||
|
logging.debug(f" # component: {c}\n")
|
||||||
|
logging.debug("\n".join(new_aliases))
|
||||||
|
|
||||||
|
# Check if all aliases from GitHub API were used
|
||||||
|
for github_alias in github_alias_dict:
|
||||||
|
if github_alias not in used_github_aliases:
|
||||||
|
logging.debug(f"# Unused Github alias: {github_alias} {github_alias_dict[github_alias]} {ascii(github_alias_dict[github_alias])}")
|
||||||
|
|
||||||
|
logging.info('\n\n Done.')
|
|
@ -0,0 +1,3 @@
|
||||||
|
emoji>=2.8.0
|
||||||
|
requests>=2.31.0
|
||||||
|
beautifulsoup4>=4.12.2
|
|
@ -0,0 +1,13 @@
|
||||||
|
@tool
|
||||||
|
extends EditorInspectorPlugin
|
||||||
|
|
||||||
|
func _can_handle(object: Object):
|
||||||
|
return object is FontIconSettings
|
||||||
|
|
||||||
|
func _parse_begin(object: Object) -> void:
|
||||||
|
var ref: FontIconSettings = object
|
||||||
|
var preview := FontIcon.new()
|
||||||
|
preview.icon_settings = ref
|
||||||
|
preview.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||||
|
preview.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||||
|
add_custom_control(preview)
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cqr75ldm2km24
|
|
@ -0,0 +1,27 @@
|
||||||
|
@tool
|
||||||
|
@icon("res://addons/icons-fonts/nodes/FontIcon.svg")
|
||||||
|
|
||||||
|
# todo add description and docs links when ready
|
||||||
|
class_name FontIcon
|
||||||
|
extends Label
|
||||||
|
|
||||||
|
@export var icon_settings := FontIconSettings.new()
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
_on_icon_settings_changed()
|
||||||
|
Utils.connect_if_possible(
|
||||||
|
icon_settings, "changed", _on_icon_settings_changed)
|
||||||
|
|
||||||
|
func _on_icon_settings_changed():
|
||||||
|
if !label_settings:
|
||||||
|
label_settings = LabelSettings.new()
|
||||||
|
|
||||||
|
icon_settings.update_label_settings(label_settings)
|
||||||
|
text = IconsFonts.get_icon_char(
|
||||||
|
icon_settings.icon_font,
|
||||||
|
icon_settings.icon_name
|
||||||
|
)
|
||||||
|
|
||||||
|
func _validate_property(property : Dictionary) -> void:
|
||||||
|
if property.name in [&"text", &"label_settings"]:
|
||||||
|
property.usage &= ~PROPERTY_USAGE_EDITOR
|
|
@ -0,0 +1 @@
|
||||||
|
uid://sfoyl3fbn8so
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="MaterialIcon.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
inkscape:export-filename="/home/jeremi360/DevProjects/Godot/Godot-Material-Icons/icon.png"
|
||||||
|
inkscape:export-xdpi="256"
|
||||||
|
inkscape:export-ydpi="256"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="33.125"
|
||||||
|
inkscape:cx="12.030189"
|
||||||
|
inkscape:cy="12.015094"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1002"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:deskcolor="#505050" />
|
||||||
|
<path
|
||||||
|
d="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M13.96,12.29L11.21,15.83L9.25,13.47L6.5,17H17.5L13.96,12.29Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#8eef97;fill-opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,37 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://drissyo4imc7c"
|
||||||
|
path="res://.godot/imported/FontIcon.svg-1bab4063a82703b60d9abf5769a35adc.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/icons-fonts/nodes/FontIcon.svg"
|
||||||
|
dest_files=["res://.godot/imported/FontIcon.svg-1bab4063a82703b60d9abf5769a35adc.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
|
|
@ -0,0 +1,133 @@
|
||||||
|
@tool
|
||||||
|
@icon("res://addons/icons-fonts/nodes/FontIconButton.svg")
|
||||||
|
|
||||||
|
# todo add description and docs links when ready
|
||||||
|
class_name FontIconButton
|
||||||
|
extends ButtonContainer
|
||||||
|
|
||||||
|
@export_group("Layout", "layout_")
|
||||||
|
@export_enum("Label-Icon", "Icon-Label", "Icon")
|
||||||
|
var layout_order := "Label-Icon":
|
||||||
|
set(value):
|
||||||
|
layout_order = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_set_order(value)
|
||||||
|
|
||||||
|
@export var layout_vertical := false:
|
||||||
|
set(value):
|
||||||
|
layout_vertical = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_box.vertical = value
|
||||||
|
|
||||||
|
@export var layout_alignment := BoxContainer.ALIGNMENT_CENTER:
|
||||||
|
set(value):
|
||||||
|
layout_alignment = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_box.alignment = value
|
||||||
|
|
||||||
|
@export_group("Icon", "icon_")
|
||||||
|
@export var icon_settings := FontIconSettings.new():
|
||||||
|
set(value):
|
||||||
|
icon_settings = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_font_icon.icon_settings = value
|
||||||
|
|
||||||
|
@export_group("Label", "label_")
|
||||||
|
@export var label_text := "":
|
||||||
|
set(value):
|
||||||
|
label_text = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_label.text = label_text
|
||||||
|
|
||||||
|
@export var label_settings := LabelSettings.new():
|
||||||
|
set(value):
|
||||||
|
label_settings = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_label.label_settings = label_settings
|
||||||
|
|
||||||
|
@export var button_margin := 5:
|
||||||
|
set(value):
|
||||||
|
button_margin = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
var margins := [
|
||||||
|
"margin_top", "margin_left",
|
||||||
|
"margin_bottom", "margin_right"
|
||||||
|
]
|
||||||
|
for margin in margins:
|
||||||
|
_margins.add_theme_constant_override(margin, button_margin)
|
||||||
|
|
||||||
|
var _font_icon: FontIcon
|
||||||
|
var _label: Label
|
||||||
|
var _box: BoxContainer
|
||||||
|
var _margins: MarginContainer
|
||||||
|
|
||||||
|
func _get_lay_dict() -> Dictionary:
|
||||||
|
return {
|
||||||
|
"Label": _label,
|
||||||
|
"Icon": _font_icon,
|
||||||
|
}
|
||||||
|
|
||||||
|
func _add_icon(_icon_settings: FontIconSettings) -> FontIcon:
|
||||||
|
var empty_style := StyleBoxEmpty.new()
|
||||||
|
var _icon = FontIcon.new()
|
||||||
|
_icon.add_theme_stylebox_override("normal", empty_style)
|
||||||
|
Utils.connect_if_possible(_icon_settings, "changed",
|
||||||
|
func(): update_icon(_icon_settings, _icon))
|
||||||
|
return _icon
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
super._ready()
|
||||||
|
for ch: Control in get_children():
|
||||||
|
ch.queue_free()
|
||||||
|
|
||||||
|
ready.connect(func(): self.layout_order = layout_order)
|
||||||
|
var empty_style := StyleBoxEmpty.new()
|
||||||
|
_box = BoxContainer.new()
|
||||||
|
_font_icon = _add_icon(icon_settings)
|
||||||
|
|
||||||
|
_label = Label.new()
|
||||||
|
_label.add_theme_stylebox_override("normal", empty_style)
|
||||||
|
|
||||||
|
_margins = MarginContainer.new()
|
||||||
|
_margins.add_child(_box)
|
||||||
|
add_child(_margins)
|
||||||
|
|
||||||
|
Utils.connect_if_possible(
|
||||||
|
label_settings, "changed",
|
||||||
|
func():
|
||||||
|
if label_settings != _label.label_settings:
|
||||||
|
_label.label_settings = label_settings
|
||||||
|
)
|
||||||
|
|
||||||
|
func update_icon(new_icon_settings: FontIconSettings, font_icon: FontIcon):
|
||||||
|
if new_icon_settings != font_icon.icon_settings:
|
||||||
|
font_icon.icon_settings = new_icon_settings
|
||||||
|
Utils.connect_if_possible(
|
||||||
|
new_icon_settings, "changed",
|
||||||
|
font_icon._on_icon_settings_changed)
|
||||||
|
|
||||||
|
func _clear_box():
|
||||||
|
if _box.get_child_count() == 0: return
|
||||||
|
for ch: Control in _box.get_children():
|
||||||
|
_box.remove_child(ch)
|
||||||
|
|
||||||
|
func _set_order(order:String):
|
||||||
|
_clear_box()
|
||||||
|
await get_tree().create_timer(0.2).timeout
|
||||||
|
_apply_layout(_crate_layout(order))
|
||||||
|
|
||||||
|
func _crate_layout(order:String) -> Array[Control]:
|
||||||
|
var layout: Array[Control] = []
|
||||||
|
var order_split := order.split("-")
|
||||||
|
var dict := _get_lay_dict()
|
||||||
|
for con in order_split:
|
||||||
|
layout.append(dict[con])
|
||||||
|
return layout
|
||||||
|
|
||||||
|
func _apply_layout(layout: Array[Control]):
|
||||||
|
for control: Control in layout:
|
||||||
|
if control.get_parent() == _box: continue
|
||||||
|
_box.add_child(control)
|
||||||
|
if control is FontIcon:
|
||||||
|
control.size_flags_horizontal\
|
||||||
|
= Control.SIZE_SHRINK_CENTER
|
|
@ -0,0 +1 @@
|
||||||
|
uid://pwyh8365is28
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="MaterialButton.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="33.125"
|
||||||
|
inkscape:cx="6.0830189"
|
||||||
|
inkscape:cy="12.015094"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1002"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:deskcolor="#505050" />
|
||||||
|
<path
|
||||||
|
d="M10.76,8.69A0.76,0.76 0 0,0 10,9.45V20.9C10,21.32 10.34,21.66 10.76,21.66C10.95,21.66 11.11,21.6 11.24,21.5L13.15,19.95L14.81,23.57C14.94,23.84 15.21,24 15.5,24C15.61,24 15.72,24 15.83,23.92L18.59,22.64C18.97,22.46 19.15,22 18.95,21.63L17.28,18L19.69,17.55C19.85,17.5 20,17.43 20.12,17.29C20.39,16.97 20.35,16.5 20,16.21L11.26,8.86L11.25,8.87C11.12,8.76 10.95,8.69 10.76,8.69M15,10V8H20V10H15M13.83,4.76L16.66,1.93L18.07,3.34L15.24,6.17L13.83,4.76M10,0H12V5H10V0M3.93,14.66L6.76,11.83L8.17,13.24L5.34,16.07L3.93,14.66M3.93,3.34L5.34,1.93L8.17,4.76L6.76,6.17L3.93,3.34M7,10H2V8H7V10"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#8eef97;fill-opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,37 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dc2hiifebeghw"
|
||||||
|
path="res://.godot/imported/FontIconButton.svg-bebb139a7209cbe8285b2004832e8f79.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/icons-fonts/nodes/FontIconButton.svg"
|
||||||
|
dest_files=["res://.godot/imported/FontIconButton.svg-bebb139a7209cbe8285b2004832e8f79.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
|
|
@ -0,0 +1,67 @@
|
||||||
|
@tool
|
||||||
|
@icon("res://addons/icons-fonts/nodes/FontIconButton.svg")
|
||||||
|
|
||||||
|
# todo add description and docs links when ready
|
||||||
|
class_name FontIconCheckButton
|
||||||
|
extends FontIconButton
|
||||||
|
|
||||||
|
@export var on_icon_settings := FontIconSettings.new():
|
||||||
|
set(value):
|
||||||
|
on_icon_settings = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_toggle_icon_on.icon_settings = value
|
||||||
|
|
||||||
|
@export var off_icon_settings := FontIconSettings.new():
|
||||||
|
set(value):
|
||||||
|
off_icon_settings = value
|
||||||
|
if !is_node_ready(): await ready
|
||||||
|
_toggle_icon_off.icon_settings = value
|
||||||
|
|
||||||
|
var _toggle_icon_on: FontIcon
|
||||||
|
var _toggle_icon_off: FontIcon
|
||||||
|
var _toggle_icon_box: BoxContainer
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
toggle_mode = true
|
||||||
|
if "Toggle" not in layout_order:
|
||||||
|
layout_order = "Label-Icon-Toggle"
|
||||||
|
|
||||||
|
super._ready()
|
||||||
|
_toggle_icon_box = BoxContainer.new()
|
||||||
|
|
||||||
|
_toggle_icon_on = _add_icon(on_icon_settings)
|
||||||
|
_toggle_icon_on.visible = button_pressed
|
||||||
|
_toggle_icon_box.add_child(_toggle_icon_on)
|
||||||
|
|
||||||
|
_toggle_icon_off = _add_icon(off_icon_settings)
|
||||||
|
_toggle_icon_off.visible = !button_pressed
|
||||||
|
_toggle_icon_box.add_child(_toggle_icon_off)
|
||||||
|
|
||||||
|
func _on_on_icon_changed():
|
||||||
|
update_icon(on_icon_settings, _toggle_icon_on)
|
||||||
|
|
||||||
|
func _on_off_icon_changed():
|
||||||
|
update_icon(off_icon_settings, _toggle_icon_on)
|
||||||
|
|
||||||
|
func _togglef(main_button: ButtonContainer, value: bool):
|
||||||
|
if disabled: return
|
||||||
|
if main_button == self: return
|
||||||
|
_toggle_icon_on.visible = value
|
||||||
|
_toggle_icon_off.visible = !value
|
||||||
|
super._togglef(main_button, value)
|
||||||
|
|
||||||
|
func _get_lay_dict() -> Dictionary:
|
||||||
|
return {
|
||||||
|
"Label": _label,
|
||||||
|
"Icon": _font_icon,
|
||||||
|
"Toggle": _toggle_icon_box
|
||||||
|
}
|
||||||
|
|
||||||
|
func _validate_property(property : Dictionary) -> void:
|
||||||
|
if property.name == &"layout_order":
|
||||||
|
property.hint_string = ",".join([
|
||||||
|
"Label-Icon-Toggle", "Label-Toggle-Icon",
|
||||||
|
"Toggle-Label-Icon", "Toggle-Icon-Label",
|
||||||
|
"Icon-Label-Toggle", "Icon-Toggle-Label",
|
||||||
|
"Label-Toggle", "Toggle-Label", "Toggle"
|
||||||
|
])
|
|
@ -0,0 +1 @@
|
||||||
|
uid://c4n2aki4724e4
|
|
@ -0,0 +1,7 @@
|
||||||
|
[plugin]
|
||||||
|
|
||||||
|
name="Godot Icons Fonts"
|
||||||
|
description="Makes easy to find and use icons from popular icon-fonts in your Godot project."
|
||||||
|
author="Jeremi Biernacki"
|
||||||
|
version="1.2.4"
|
||||||
|
script="icons_fonts.gd"
|
|
@ -0,0 +1,67 @@
|
||||||
|
@tool
|
||||||
|
@icon("res://addons/icons-fonts/resources/FontIconSettings.svg")
|
||||||
|
class_name FontIconSettings
|
||||||
|
extends Resource
|
||||||
|
|
||||||
|
@export_enum("MaterialIcons", "Emojis")
|
||||||
|
var icon_font := "MaterialIcons"
|
||||||
|
|
||||||
|
## Name of Icon to display
|
||||||
|
@export var icon_name := "image-outline":
|
||||||
|
set(value):
|
||||||
|
icon_name = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
## Size of the icon in range 16-128
|
||||||
|
@export_range(16, 128, 1)
|
||||||
|
var icon_size := 16:
|
||||||
|
set(value):
|
||||||
|
icon_size = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
@export var icon_color := Color.WHITE:
|
||||||
|
set(value):
|
||||||
|
icon_color = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
@export_group("Outline", "outline_")
|
||||||
|
@export var outline_color := Color.WHITE:
|
||||||
|
set(value):
|
||||||
|
outline_color = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
@export var outline_size := 0:
|
||||||
|
set(value):
|
||||||
|
outline_size = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
@export_group("Shadow", "shadow_")
|
||||||
|
@export var shadow_color := Color.WHITE:
|
||||||
|
set(value):
|
||||||
|
shadow_color = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
@export var shadow_size := 0:
|
||||||
|
set(value):
|
||||||
|
shadow_size = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
@export var shadow_offset := Vector2.ZERO:
|
||||||
|
set(value):
|
||||||
|
shadow_offset = value
|
||||||
|
emit_changed()
|
||||||
|
|
||||||
|
func update_label_settings(label_settings: LabelSettings) -> void:
|
||||||
|
match icon_font:
|
||||||
|
"MaterialIcons":
|
||||||
|
label_settings.font = load(IconsFonts.material_icons_font)
|
||||||
|
"Emojis":
|
||||||
|
label_settings.font = load(IconsFonts.emojis_font)
|
||||||
|
|
||||||
|
label_settings.font_size = icon_size
|
||||||
|
label_settings.font_color = icon_color
|
||||||
|
label_settings.outline_color = outline_color
|
||||||
|
label_settings.outline_size = outline_size
|
||||||
|
label_settings.shadow_color = shadow_color
|
||||||
|
label_settings.shadow_offset = shadow_offset
|
||||||
|
label_settings.shadow_size = shadow_size
|
|
@ -0,0 +1 @@
|
||||||
|
uid://dpyof2t0wn8k1
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="24px"
|
||||||
|
viewBox="0 -960 960 960"
|
||||||
|
width="24px"
|
||||||
|
fill="#e8eaed"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
sodipodi:docname="FontIconSettings.svg"
|
||||||
|
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="33.708333"
|
||||||
|
inkscape:cx="11.985167"
|
||||||
|
inkscape:cy="12"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1008"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg1" />
|
||||||
|
<path
|
||||||
|
d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"
|
||||||
|
id="path1"
|
||||||
|
style="fill:#8eef97;fill-opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,37 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://87qmm7ao6o7k"
|
||||||
|
path="res://.godot/imported/FontIconSettings.svg-52a3d7fa565f0354cb3aa78380db99bf.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/icons-fonts/resources/FontIconSettings.svg"
|
||||||
|
dest_files=["res://.godot/imported/FontIconSettings.svg-52a3d7fa565f0354cb3aa78380db99bf.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
|
|
@ -0,0 +1,9 @@
|
||||||
|
@tool
|
||||||
|
extends ButtonContainer
|
||||||
|
|
||||||
|
@onready var label: Label = $Label
|
||||||
|
|
||||||
|
|
||||||
|
func _on_toggled(value: bool) -> void:
|
||||||
|
if value: label.text = "Pressed"
|
||||||
|
else: label.text = "UnPressed"
|
|
@ -0,0 +1 @@
|
||||||
|
uid://b31livnmee5ew
|
|
@ -0,0 +1,86 @@
|
||||||
|
[gd_scene load_steps=3 format=3 uid="uid://bmpgup35ifpet"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/rakugo-nodes/examples/button_container_example.gd" id="1_dy71b"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_g1pbs"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0.1, 0.1, 0.1, 0.6)
|
||||||
|
corner_radius_top_left = 3
|
||||||
|
corner_radius_top_right = 3
|
||||||
|
corner_radius_bottom_right = 3
|
||||||
|
corner_radius_bottom_left = 3
|
||||||
|
corner_detail = 5
|
||||||
|
|
||||||
|
[node name="Example" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="BoxContainer2" type="BoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -129.5
|
||||||
|
offset_top = -20.0
|
||||||
|
offset_right = 129.5
|
||||||
|
offset_bottom = 20.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
vertical = true
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="BoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "RadioMode Test"
|
||||||
|
|
||||||
|
[node name="BoxContainer" type="BoxContainer" parent="BoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ButtonContainer" type="PanelContainer" parent="BoxContainer2/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_g1pbs")
|
||||||
|
script = ExtResource("1_dy71b")
|
||||||
|
toggle_mode = true
|
||||||
|
radio_mode = true
|
||||||
|
button_pressed = true
|
||||||
|
button_group = &"example"
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="BoxContainer2/BoxContainer/ButtonContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Pressed"
|
||||||
|
|
||||||
|
[node name="ButtonContainer2" type="PanelContainer" parent="BoxContainer2/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_g1pbs")
|
||||||
|
script = ExtResource("1_dy71b")
|
||||||
|
toggle_mode = true
|
||||||
|
radio_mode = true
|
||||||
|
button_group = &"example"
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="BoxContainer2/BoxContainer/ButtonContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "UnPressed"
|
||||||
|
|
||||||
|
[node name="ButtonContainer3" type="PanelContainer" parent="BoxContainer2/BoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_g1pbs")
|
||||||
|
script = ExtResource("1_dy71b")
|
||||||
|
toggle_mode = true
|
||||||
|
radio_mode = true
|
||||||
|
button_group = &"example"
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="BoxContainer2/BoxContainer/ButtonContainer3"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "UnPressed"
|
||||||
|
|
||||||
|
[connection signal="toggled" from="BoxContainer2/BoxContainer/ButtonContainer" to="BoxContainer2/BoxContainer/ButtonContainer" method="_on_toggled"]
|
||||||
|
[connection signal="toggled" from="BoxContainer2/BoxContainer/ButtonContainer2" to="BoxContainer2/BoxContainer/ButtonContainer2" method="_on_toggled"]
|
||||||
|
[connection signal="toggled" from="BoxContainer2/BoxContainer/ButtonContainer3" to="BoxContainer2/BoxContainer/ButtonContainer3" method="_on_toggled"]
|
|
@ -0,0 +1,139 @@
|
||||||
|
@tool
|
||||||
|
@icon("res://addons/custom-ui-elements/nodes/ButtonContainer.svg")
|
||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
# todo add description and docs links when ready
|
||||||
|
class_name ButtonContainer
|
||||||
|
|
||||||
|
## Emitted when button is pressed
|
||||||
|
signal pressed
|
||||||
|
|
||||||
|
## Emitted when button is toggled
|
||||||
|
## Works only if `toggle_mode` is on.
|
||||||
|
signal toggled(value: bool)
|
||||||
|
|
||||||
|
signal state_changed(state_name: StringName)
|
||||||
|
|
||||||
|
## If true, button will be disabled
|
||||||
|
@export var disabled := false:
|
||||||
|
set(value):
|
||||||
|
disabled = value
|
||||||
|
if disabled:
|
||||||
|
_change_stylebox("disabled")
|
||||||
|
state_changed.emit(&"disabled")
|
||||||
|
return
|
||||||
|
|
||||||
|
_change_stylebox("normal")
|
||||||
|
state_changed.emit(&"normal")
|
||||||
|
|
||||||
|
## If true, button will be in toggle mode
|
||||||
|
@export var toggle_mode := false
|
||||||
|
var _toggled := false:
|
||||||
|
get: return _toggled
|
||||||
|
|
||||||
|
## If true, button will be in pressed state
|
||||||
|
@export var button_pressed := false:
|
||||||
|
set(value):
|
||||||
|
if toggle_mode:
|
||||||
|
button_pressed = value
|
||||||
|
_togglef(null, value)
|
||||||
|
return
|
||||||
|
|
||||||
|
emit_signal("pressed")
|
||||||
|
|
||||||
|
## Name of node group to be used as button group
|
||||||
|
## It changes all buttons with toggle_mode in group into radio buttons
|
||||||
|
@export var button_group: StringName = ""
|
||||||
|
|
||||||
|
@export_group("Styles", "style_")
|
||||||
|
@export var style_normal: StyleBox:
|
||||||
|
set(value):
|
||||||
|
style_normal = value
|
||||||
|
if !disabled or !button_pressed:
|
||||||
|
_change_stylebox("normal")
|
||||||
|
|
||||||
|
@export var style_focus: StyleBox
|
||||||
|
|
||||||
|
@export var style_pressed: StyleBox:
|
||||||
|
set(value):
|
||||||
|
style_pressed = value
|
||||||
|
if !disabled and button_pressed:
|
||||||
|
_change_stylebox("pressed")
|
||||||
|
|
||||||
|
@export var style_hover: StyleBox
|
||||||
|
|
||||||
|
@export var style_disabled: StyleBox:
|
||||||
|
set(value):
|
||||||
|
style_disabled = value
|
||||||
|
if disabled:
|
||||||
|
_change_stylebox("disabled")
|
||||||
|
|
||||||
|
var current_style: StringName
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_change_stylebox("normal")
|
||||||
|
state_changed.emit(&"normal")
|
||||||
|
Utils.connect_if_possible(self, &"mouse_entered", _on_mouse_entered)
|
||||||
|
Utils.connect_if_possible(self, &"mouse_exited", _on_mouse_exited)
|
||||||
|
|
||||||
|
if button_group: add_to_group(button_group)
|
||||||
|
|
||||||
|
func _on_mouse_exited():
|
||||||
|
if disabled: return
|
||||||
|
if toggle_mode and _toggled: return
|
||||||
|
_change_stylebox("normal")
|
||||||
|
state_changed.emit(&"normal")
|
||||||
|
|
||||||
|
func _on_mouse_entered():
|
||||||
|
if disabled: return
|
||||||
|
_change_stylebox("hover")
|
||||||
|
state_changed.emit(&"hover")
|
||||||
|
|
||||||
|
func _change_stylebox(button_style: StringName = "normal"):
|
||||||
|
# prints("changed style to:", button_style)
|
||||||
|
var stylebox := get_theme_stylebox(button_style, "Button")
|
||||||
|
match button_style:
|
||||||
|
"normal":
|
||||||
|
stylebox = style_normal if style_normal else stylebox
|
||||||
|
"focus":
|
||||||
|
stylebox = style_focus if style_focus else stylebox
|
||||||
|
"pressed":
|
||||||
|
stylebox = style_pressed if style_pressed else stylebox
|
||||||
|
"hover":
|
||||||
|
stylebox = style_hover if style_hover else stylebox
|
||||||
|
"disabled":
|
||||||
|
stylebox = style_disabled if style_disabled else stylebox
|
||||||
|
|
||||||
|
if current_style != button_style:
|
||||||
|
current_style = button_style
|
||||||
|
add_theme_stylebox_override("panel", stylebox)
|
||||||
|
|
||||||
|
func _gui_input(event: InputEvent) -> void:
|
||||||
|
if disabled: return
|
||||||
|
if event is InputEventMouseButton:
|
||||||
|
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||||
|
if toggle_mode:
|
||||||
|
var t := !_toggled
|
||||||
|
_togglef(null, t)
|
||||||
|
|
||||||
|
if button_group:
|
||||||
|
get_tree().call_group(
|
||||||
|
button_group, "_togglef", self, !t)
|
||||||
|
return
|
||||||
|
|
||||||
|
state_changed.emit(&"pressed")
|
||||||
|
pressed.emit()
|
||||||
|
|
||||||
|
func _togglef(main_button: ButtonContainer, value: bool):
|
||||||
|
if disabled: return
|
||||||
|
if main_button == self: return
|
||||||
|
|
||||||
|
_toggled = value
|
||||||
|
if value:
|
||||||
|
_change_stylebox("pressed")
|
||||||
|
state_changed.emit(&"pressed")
|
||||||
|
else:
|
||||||
|
_change_stylebox("normal")
|
||||||
|
state_changed.emit(&"normal")
|
||||||
|
|
||||||
|
toggled.emit(_toggled)
|
|
@ -0,0 +1 @@
|
||||||
|
uid://c63iqxnesjokx
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="24px"
|
||||||
|
viewBox="0 -960 960 960"
|
||||||
|
width="24px"
|
||||||
|
fill="#e8eaed"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
sodipodi:docname="ButtonBox.svg"
|
||||||
|
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="33.708333"
|
||||||
|
inkscape:cx="11.777503"
|
||||||
|
inkscape:cy="11.851669"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1008"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg1" />
|
||||||
|
<path
|
||||||
|
d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H160v320Zm130-40h60v-90h90v-60h-90v-90h-60v90h-90v60h90v90Zm-130 40v-320 320Z"
|
||||||
|
id="path1"
|
||||||
|
style="fill:#8eef97;fill-opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,37 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://d4nquc8rmh42g"
|
||||||
|
path="res://.godot/imported/ButtonContainer.svg-2244ab290648c46839f5024e765ecf96.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/rakugo-nodes/nodes/ButtonContainer.svg"
|
||||||
|
dest_files=["res://.godot/imported/ButtonContainer.svg-2244ab290648c46839f5024e765ecf96.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
|
|
@ -0,0 +1,7 @@
|
||||||
|
[plugin]
|
||||||
|
|
||||||
|
name="Rakugo Nodes"
|
||||||
|
description="Collection of various custom Nodes"
|
||||||
|
author="Jeremi Biernacki"
|
||||||
|
version="1.1"
|
||||||
|
script="rakugo_nodes.gd"
|
|
@ -0,0 +1,8 @@
|
||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _exit_tree():
|
||||||
|
pass
|
|
@ -0,0 +1 @@
|
||||||
|
uid://dk1343vabbdpj
|
|
@ -0,0 +1,27 @@
|
||||||
|
class_name Utils
|
||||||
|
extends Object
|
||||||
|
|
||||||
|
## Is shortcut of:
|
||||||
|
## if !object.is_connected(signal_name, method):
|
||||||
|
## object.connect(signal_name, method)
|
||||||
|
static func connect_if_possible(
|
||||||
|
object:Object, signal_name:StringName, method:Callable):
|
||||||
|
if !object.is_connected(signal_name, method):
|
||||||
|
object.connect(signal_name, method)
|
||||||
|
|
||||||
|
## Is shortcut of:
|
||||||
|
## if object.is_connected(signal_name, method):
|
||||||
|
## object.disconnect(signal_name, method)
|
||||||
|
static func disconnect_if_possible(
|
||||||
|
object:Object, signal_name:StringName, method:Callable):
|
||||||
|
if object.is_connected(signal_name, method):
|
||||||
|
object.disconnect(signal_name, method)
|
||||||
|
|
||||||
|
## Is shortcut of:
|
||||||
|
## disconnect_if_possible(object, signal_name, old_method)
|
||||||
|
## connect_if_possible(object, signal_name, new_method)
|
||||||
|
static func change_signal(
|
||||||
|
object:Object, signal_name:StringName,
|
||||||
|
old_method:Callable, new_method:Callable):
|
||||||
|
disconnect_if_possible(object, signal_name, old_method)
|
||||||
|
connect_if_possible(object, signal_name, new_method)
|
|
@ -0,0 +1 @@
|
||||||
|
uid://1cdqubssue7k
|
Loading…
Reference in New Issue