diff --git a/Translations/Translations.pot b/Translations/Translations.pot index 8afcb498e05..bc63b953c40 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -828,6 +828,10 @@ msgstr "" msgid "Display scale:" msgstr "" +#. Refers to the font of a text. +msgid "Font:" +msgstr "" + #. Found in the preferences, under the interface section. Allows users to set the size of the font, ie the text. msgid "Font size:" msgstr "" diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 98444e866e8..46f430172f3 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -163,6 +163,9 @@ var default_layouts: Array[DockableLayout] = [ preload("res://assets/layouts/Tallscreen.tres"), ] var layouts: Array[DockableLayout] = [] +var loaded_fonts: Array[Font] = [ + ThemeDB.fallback_font, preload("res://assets/fonts/Roboto-Regular.ttf") +] # Canvas related stuff ## Tells if the user allowed to draw on the canvas. Usually it is temporarily set to @@ -604,7 +607,6 @@ var cel_button_scene: PackedScene = load("res://src/UI/Timeline/CelButton.tscn") ## The control node (aka Main node). It has the [param Main.gd] script attached. @onready var control := get_tree().current_scene as Control - ## The project tabs bar. It has the [param Tabs.gd] script attached. @onready var tabs: TabBar = control.find_child("TabBar") ## Contains viewport of the main canvas. It has the [param ViewportContainer.gd] script attached. @@ -617,7 +619,6 @@ var cel_button_scene: PackedScene = load("res://src/UI/Timeline/CelButton.tscn") @onready var camera: CanvasCamera = main_viewport.find_child("Camera2D") ## Transparent checker of the main canvas. It has the [param TransparentChecker.gd] script attached. @onready var transparent_checker: ColorRect = control.find_child("TransparentChecker") - ## The perspective editor. It has the [param PerspectiveEditor.gd] script attached. @onready var perspective_editor := control.find_child("Perspective Editor") ## The top menu container. It has the [param TopMenuContainer.gd] script attached. @@ -634,7 +635,6 @@ var cel_button_scene: PackedScene = load("res://src/UI/Timeline/CelButton.tscn") @onready var cel_vbox: VBoxContainer = animation_timeline.find_child("CelVBox") ## The container of animation tags. @onready var tag_container: Control = animation_timeline.find_child("TagContainer") - ## The brushes popup dialog used to display brushes. ## It has the [param BrushesPopup.gd] script attached. @onready var brushes_popup: Popup = control.find_child("BrushesPopup") @@ -1028,6 +1028,32 @@ func find_nearest_locale(locale: String) -> String: return closest_locale +func get_available_font_names() -> PackedStringArray: + var font_names := PackedStringArray() + for font in loaded_fonts: + var font_name := font.get_font_name() + if font_name in font_names: + continue + font_names.append(font_name) + for system_font_name in OS.get_system_fonts(): + if system_font_name in font_names: + continue + font_names.append(system_font_name) + return font_names + + +func find_font_from_name(font_name: String) -> Font: + for font in loaded_fonts: + if font.get_font_name() == font_name: + return font + for system_font_name in OS.get_system_fonts(): + if system_font_name == font_name: + var system_font := SystemFont.new() + system_font.font_names = [font_name] + return system_font + return ThemeDB.fallback_font + + ## Used by undo/redo operations to store compressed images in memory. ## [param redo_data] and [param undo_data] are Dictionaries, ## with keys of type [Image] and [Dictionary] values, coming from [member Image.data]. diff --git a/src/Classes/Cel3DObject.gd b/src/Classes/Cel3DObject.gd index e1bd6745549..b988d51ecf0 100644 --- a/src/Classes/Cel3DObject.gd +++ b/src/Classes/Cel3DObject.gd @@ -93,6 +93,7 @@ func serialize() -> Dictionary: dict["mesh_ring_segments"] = mesh.ring_segments dict["mesh_rings"] = mesh.rings Type.TEXT: + dict["mesh_font_name"] = mesh.font.get_font_name() dict["mesh_text"] = mesh.text dict["mesh_pixel_size"] = mesh.pixel_size dict["mesh_font_size"] = mesh.font_size @@ -156,6 +157,7 @@ func deserialize(dict: Dictionary) -> void: mesh.ring_segments = dict["mesh_ring_segments"] mesh.rings = dict["mesh_rings"] Type.TEXT: + mesh.font = Global.find_font_from_name(dict["mesh_font_name"]) mesh.text = dict["mesh_text"] mesh.pixel_size = dict["mesh_pixel_size"] mesh.font_size = dict["mesh_font_size"] diff --git a/src/Tools/3DTools/3DShapeEdit.gd b/src/Tools/3DTools/3DShapeEdit.gd index 939dcd637c5..8e3c8a3485e 100644 --- a/src/Tools/3DTools/3DShapeEdit.gd +++ b/src/Tools/3DTools/3DShapeEdit.gd @@ -58,6 +58,7 @@ var _object_names := { "node3d_type:mesh:top_radius": $"%MeshTopRadius", "node3d_type:mesh:bottom_radius": $"%MeshBottomRadius", "node3d_type:mesh:text": $"%MeshText", + "node3d_type:mesh:font": $"%MeshFont", "node3d_type:mesh:pixel_size": $"%MeshPixelSize", "node3d_type:mesh:font_size": $"%MeshFontSize", "node3d_type:mesh:offset": $"%MeshOffsetV2", @@ -98,6 +99,10 @@ func _ready() -> void: for object in _object_names: new_object_popup.add_item(_object_names[object], object) new_object_popup.id_pressed.connect(_new_object_popup_id_pressed) + # Load font names + for font_name in Global.get_available_font_names(): + $"%MeshFont".add_item(font_name) + # Connect the signals of the cel property nodes for prop in cel_properties: var node: Control = cel_properties[prop] if node is ValueSliderV3: @@ -108,6 +113,7 @@ func _ready() -> void: node.item_selected.connect(_cel_property_item_selected.bind(prop)) elif node is ColorPickerButton: node.color_changed.connect(_cel_property_color_changed.bind(prop)) + # Connect the signals of the object property nodes for prop in object_properties: var node: Control = object_properties[prop] if node is ValueSliderV3: @@ -365,6 +371,13 @@ func _set_node_values(to_edit: Object, properties: Dictionary) -> void: continue if "scale" in prop: value *= 100 + if value is Font: + var font_name: String = value.get_font_name() + value = 0 + for i in %MeshFont.item_count: + var item_name: String = %MeshFont.get_item_text(i) + if font_name == item_name: + value = i var node: Control = properties[prop] if node is Range or node is ValueSliderV3 or node is ValueSliderV2: if typeof(node.value) != typeof(value) and typeof(value) != TYPE_INT: @@ -393,6 +406,8 @@ func _set_value_from_node(to_edit: Object, value, prop: String) -> void: to_edit = to_edit.node3d_type.mesh if "scale" in prop: value /= 100 + if "font" in prop and not "font_" in prop: + value = Global.find_font_from_name(%MeshFont.get_item_text(value)) to_edit.set_indexed(prop, value) diff --git a/src/Tools/3DTools/3DShapeEdit.tscn b/src/Tools/3DTools/3DShapeEdit.tscn index c2bbda60ac4..8902c834c98 100644 --- a/src/Tools/3DTools/3DShapeEdit.tscn +++ b/src/Tools/3DTools/3DShapeEdit.tscn @@ -510,13 +510,26 @@ custom_minimum_size = Vector2(150, 50) layout_mode = 2 size_flags_horizontal = 3 -[node name="MeshPixelSizeLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="22"] +[node name="MeshFontLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="22"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Font:" +clip_text = true + +[node name="MeshFont" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="23"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +mouse_default_cursor_shape = 2 +selected = 0 + +[node name="MeshPixelSizeLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="24"] layout_mode = 2 size_flags_horizontal = 3 text = "Pixel size:" clip_text = true -[node name="MeshPixelSize" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="23"] +[node name="MeshPixelSize" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="25"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -536,13 +549,13 @@ stretch_margin_bottom = 3 script = ExtResource("5") snap_step = 0.01 -[node name="MeshFontSizeLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="24"] +[node name="MeshFontSizeLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="26"] layout_mode = 2 size_flags_horizontal = 3 text = "Font size:" clip_text = true -[node name="MeshFontSize" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="25"] +[node name="MeshFontSize" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="27"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -561,13 +574,13 @@ stretch_margin_bottom = 3 script = ExtResource("5") snap_step = 2.0 -[node name="MeshDepthLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="26"] +[node name="MeshDepthLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="28"] layout_mode = 2 size_flags_horizontal = 3 text = "Depth:" clip_text = true -[node name="MeshDepth" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="27"] +[node name="MeshDepth" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="29"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -585,13 +598,13 @@ stretch_margin_bottom = 3 script = ExtResource("5") snap_step = 2.0 -[node name="MeshOffsetLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="28"] +[node name="MeshOffsetLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="30"] layout_mode = 2 size_flags_horizontal = 3 text = "Offset:" clip_text = true -[node name="MeshOffsetV2" parent="ObjectOptions/MeshOptions/GridContainer" index="29" instance=ExtResource("3")] +[node name="MeshOffsetV2" parent="ObjectOptions/MeshOptions/GridContainer" index="31" instance=ExtResource("3")] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -601,13 +614,13 @@ allow_lesser = true show_ratio = true snap_step = 0.01 -[node name="MeshCurveStepLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="30"] +[node name="MeshCurveStepLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="32"] layout_mode = 2 size_flags_horizontal = 3 text = "Curve step:" clip_text = true -[node name="MeshCurveStep" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="31"] +[node name="MeshCurveStep" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="33"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -626,13 +639,13 @@ stretch_margin_right = 3 stretch_margin_bottom = 3 script = ExtResource("5") -[node name="MeshHorizontalAlignmentLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="32"] +[node name="MeshHorizontalAlignmentLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="34"] layout_mode = 2 size_flags_horizontal = 3 text = "Horizontal alignment:" clip_text = true -[node name="MeshHorizontalAlignment" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="33"] +[node name="MeshHorizontalAlignment" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="35"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -647,13 +660,13 @@ popup/item_2/id = 2 popup/item_3/text = "Fill" popup/item_3/id = 3 -[node name="MeshVerticalAlignmentLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="34"] +[node name="MeshVerticalAlignmentLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="36"] layout_mode = 2 size_flags_horizontal = 3 text = "Vertical alignment:" clip_text = true -[node name="MeshVerticalAlignment" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="35"] +[node name="MeshVerticalAlignment" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="37"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -666,13 +679,13 @@ popup/item_1/id = 1 popup/item_2/text = "Bottom" popup/item_2/id = 2 -[node name="MeshLineSpacingLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="36"] +[node name="MeshLineSpacingLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="38"] layout_mode = 2 size_flags_horizontal = 3 text = "Line spacing:" clip_text = true -[node name="MeshLineSpacing" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="37"] +[node name="MeshLineSpacing" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="39"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3