diff options
| -rw-r--r-- | client/game.gd | 13 | ||||
| -rw-r--r-- | client/global.gd | 6 | ||||
| -rw-r--r-- | client/gui/components/message/renderer.gd | 12 | ||||
| -rw-r--r-- | client/gui/components/message/renderer.tscn | 3 | ||||
| -rw-r--r-- | client/gui/menus/book/book.gd | 9 | ||||
| -rw-r--r-- | client/gui/menus/book/diagram.gd | 2 | ||||
| -rw-r--r-- | client/gui/overlays/popup_message/font_variation.tres | 10 | ||||
| -rw-r--r-- | client/gui/overlays/popup_message/popup_message.gd | 7 | ||||
| -rw-r--r-- | client/gui/overlays/popup_message/server_message.gd | 53 | ||||
| -rw-r--r-- | client/gui/overlays/popup_message/server_message.tscn | 35 | ||||
| -rw-r--r-- | client/message_parser.gd | 35 |
11 files changed, 121 insertions, 64 deletions
diff --git a/client/game.gd b/client/game.gd index 87a3ce2e..b4221fd3 100644 --- a/client/game.gd +++ b/client/game.gd @@ -236,8 +236,7 @@ func handle_packet(p): var timeout_remaining: float = p.timeout.remaining if p.timeout != null else 5. var pinned: bool = p.timeout.pinned if p.timeout != null and "pinned" in p.timeout else false if p.message != null: - var m = MessageParser.new(p.message) - m.parse(self) + var m = MessageParser.new(p.message, self) match m.kind: MessageParser.Kind.ITEM: var item_name: String = m.result @@ -358,12 +357,10 @@ func handle_packet(p): "book": menu.submenu("res://gui/menus/book/book.tscn", BookMenu.BookData.new(self, p.data)) "server_message": - var m := MessageParser.new(p.message) - m.parse(self) if p.error: - overlay_popup_message.display_server_msg(tr("c.error.server").format([m.result])) + overlay_popup_message.display_server_msg(tr("c.error.server").format([MessageParser.new(p.message, self).result])) else: - overlay_popup_message.display_server_msg(m.result) + overlay_popup_message.display_server_msg(MessageParser.new(p.message, self).result) "server_hint": if p.player != my_player_id: return @@ -375,13 +372,13 @@ func handle_packet(p): if message == null: overlay_popup_message.clear_server_msg() else: - overlay_popup_message.display_server_msg(MessageParser.new(message).parse(self), false) + overlay_popup_message.display_server_msg(MessageParser.new(message, self).result, false) else: # Positional hint message if message == null: overlay_popup_message.clear_server_msg(position_) else: - overlay_popup_message.display_server_msg_positional(MessageParser.new(message).parse(self), position_, false) + overlay_popup_message.display_server_msg_positional(MessageParser.new(message, self).result, position_, false) "environment": $Environment.update(p.effects) "redirect": diff --git a/client/global.gd b/client/global.gd index 4fe3d52e..bcf44998 100644 --- a/client/global.gd +++ b/client/global.gd @@ -114,12 +114,6 @@ func find_menu(node: Node) -> Menu: if node is Menu: return node else: return find_menu(node.get_parent()) -# TODO: move function into MessageParser -func get_message_str(m: Dictionary) -> String: - if "text" in m: return m.text - if "translation" in m: return tr(m.translation.id).format(m.translation.params.map(get_message_str)) - return "[unsupported message type]" - func language_list(): var a = TranslationServer.get_loaded_locales() a.sort() diff --git a/client/gui/components/message/renderer.gd b/client/gui/components/message/renderer.gd index 32437c8c..9520caca 100644 --- a/client/gui/components/message/renderer.gd +++ b/client/gui/components/message/renderer.gd @@ -21,9 +21,6 @@ enum Mode { TILES } -@onready var camera = $SubViewport/Node3D/Camera3D -@onready var base = $SubViewport/Node3D - var current_object: Node3D = null var mode: Mode @@ -31,11 +28,12 @@ func setup_object(object_name: String): if current_object: current_object.queue_free() match mode: Mode.ITEMS: - current_object = ItemFactory.produce(object_name, base) + current_object = ItemFactory.produce(object_name, $SubViewport/Node3D/Base) + current_object.rotation.y = 0.25 * PI + $SubViewport/Node3D/Camera3D.size = 1. Mode.TILES: var tf = TileFactory.new() current_object = tf.produce(object_name, Vector2i(0, 0), ["counter", "floor", "counter", null]) - current_object.rotation_degrees.y = 45. current_object.translate(Vector3(-0.5, 0.0, -0.5)) - camera.size = 2. - base.add_child(current_object) + $SubViewport/Node3D/Camera3D.size = 2. + $SubViewport/Node3D/Base.add_child(current_object) diff --git a/client/gui/components/message/renderer.tscn b/client/gui/components/message/renderer.tscn index 4561843f..57797eb5 100644 --- a/client/gui/components/message/renderer.tscn +++ b/client/gui/components/message/renderer.tscn @@ -38,3 +38,6 @@ far = 30.0 [node name="DirectionalLight3D" type="DirectionalLight3D" parent="SubViewport/Node3D"] transform = Transform3D(0.7071067, 0.49999997, -0.4999999, 0, 0.70710677, 0.7071067, 0.7071067, -0.49999997, 0.4999999, 0, 0, 0) + +[node name="Base" type="Node3D" parent="SubViewport/Node3D"] +transform = Transform3D(0.70710677, 0, 0.70710677, 0, 1, 0, -0.70710677, 0, 0.70710677, 0, 0, 0) diff --git a/client/gui/menus/book/book.gd b/client/gui/menus/book/book.gd index f6d95c8a..768259ad 100644 --- a/client/gui/menus/book/book.gd +++ b/client/gui/menus/book/book.gd @@ -53,17 +53,16 @@ func build_page() -> void: var p: Dictionary = pages[current_page] match p.page_type: "contents": - var title := build_title(MessageParser.new(p["title"]).parse(book_data.game)) + var title := build_title(MessageParser.new(p["title"], book_data.game).result) var vbox := VBoxContainer.new() vbox.add_child(title) for i: Array in p.table: - var m := MessageParser.new(i[0]) - m.parse(book_data.game) + var m := MessageParser.new(i[0], book_data.game) vbox.add_child(build_contents_entry(m.result, i[1])) second.add_child(vbox) "recipe": - var title := build_title(MessageParser.new(p["title"]).parse(book_data.game)) - var par := build_paragraph(MessageParser.new(p["description"]).parse(book_data.game)) + var title := build_title(MessageParser.new(p["title"], book_data.game).result) + var par := build_paragraph(MessageParser.new(p["description"], book_data.game).result) var vbox := VBoxContainer.new() vbox.add_child(title) vbox.add_child(par) diff --git a/client/gui/menus/book/diagram.gd b/client/gui/menus/book/diagram.gd index 65209c64..a57bcfc9 100644 --- a/client/gui/menus/book/diagram.gd +++ b/client/gui/menus/book/diagram.gd @@ -33,7 +33,7 @@ class DiagramNode: func _init(raw: Dictionary, game: Game): position = Vector2(raw["position"][0], raw["position"][1]) - label = MessageParser.new(raw["label"]) + label = MessageParser.new(raw["label"], game) style = raw["style"] label.parse(game) diff --git a/client/gui/overlays/popup_message/font_variation.tres b/client/gui/overlays/popup_message/font_variation.tres new file mode 100644 index 00000000..ad394ae7 --- /dev/null +++ b/client/gui/overlays/popup_message/font_variation.tres @@ -0,0 +1,10 @@ +[gd_resource type="FontVariation" load_steps=2 format=3 uid="uid://c4g6ucr5piwy1"] + +[ext_resource type="FontFile" uid="uid://bk704sc5gkrb3" path="res://gui/resources/fonts/font-azaret-mono.woff2" id="1_gewoj"] + +[resource] +resource_local_to_scene = true +base_font = ExtResource("1_gewoj") +variation_opentype = { +2003265652: 400 +} diff --git a/client/gui/overlays/popup_message/popup_message.gd b/client/gui/overlays/popup_message/popup_message.gd index 47ad6088..dd4c67bf 100644 --- a/client/gui/overlays/popup_message/popup_message.gd +++ b/client/gui/overlays/popup_message/popup_message.gd @@ -22,7 +22,6 @@ var positional_messages = {} @onready var positional_messages_node: Control = $Positional @onready var server_msg = $Static/VBox/ServerMessage -@onready var server_msg_label: Label = $Static/VBox/ServerMessage/CenterContainer/Label @onready var server_msg_timer: Timer = $ServerMessage @onready var game: Game = $"../../Game" # TODO @@ -45,9 +44,9 @@ func _process(_delta: float): msg.last_size = msg.node.size msg.node.position = -0.5 * msg.last_size -func display_server_msg(msg: String, auto_remove := true): +func display_server_msg(msg, auto_remove := true): server_msg.show() - server_msg_label.text = msg + server_msg.set_text(msg) if auto_remove: server_msg_timer.start() @@ -55,7 +54,7 @@ func display_server_msg(msg: String, auto_remove := true): func _on_server_timeout() -> void: clear_server_msg() -func display_server_msg_positional(text: String, pos: Vector2, use_monospace: bool): +func display_server_msg_positional(text, pos: Vector2, use_monospace: bool): var msg := PositionalMessage.new() msg.node = SERVER_MESSAGE_SCENE.instantiate() msg.node_2d = Node2D.new() diff --git a/client/gui/overlays/popup_message/server_message.gd b/client/gui/overlays/popup_message/server_message.gd index 76ff9361..ad3c5ed3 100644 --- a/client/gui/overlays/popup_message/server_message.gd +++ b/client/gui/overlays/popup_message/server_message.gd @@ -18,11 +18,54 @@ class_name ServerMessage const DEFAULT_FONT = preload("res://gui/resources/fonts/font-josefin-sans.woff2") const MONOSPACE_FONT = preload("res://gui/resources/fonts/font-azaret-mono.woff2") +const RENDERER = preload("res://gui/components/message/renderer.tscn") -@onready var label: Label = $CenterContainer/Label +@onready var flow: VFlowContainer = $CenterContainer/VFlowContainer -func set_text(text: String, use_monospace := true): - label.text = text - var font: FontVariation = label.get_theme_font("font") +func set_text(text, use_monospace := true): + for c: Node in flow.get_children(): + c.queue_free() + if text is String: + flow.add_child(build_label(text, use_monospace)) + elif text is Array: + for e: MessageParser in text: + var c: Control = build_message(e, use_monospace) + c.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN + c.size_flags_vertical = Control.SIZE_EXPAND_FILL + flow.add_child(c) + +static func font_size(use_monospace: bool): + return 16 if use_monospace else 20 + +func build_label(text: String, use_monospace: bool) -> Label: + var label = Label.new() + var font: FontVariation = preload("res://gui/overlays/popup_message/font_variation.tres") + var sb := StyleBoxEmpty.new() font.base_font = MONOSPACE_FONT if use_monospace else DEFAULT_FONT - label.add_theme_font_size_override("font_size", 16 if use_monospace else 20) + label.add_theme_font_size_override("font_size", font_size(use_monospace)) + label.add_theme_font_override("font", font) + label.add_theme_color_override("font_color", Color.BLACK) + label.add_theme_stylebox_override("normal", sb) + label.autowrap_mode = TextServer.AUTOWRAP_OFF + label.text = text + label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + label.update_minimum_size() + return label + +func build_message(m: MessageParser, use_monospace: bool) -> Control: + match m.kind: + MessageParser.Kind.ITEM: + var r: Renderer = RENDERER.instantiate() + r.get_node("SubViewport").size = Vector2i.ONE * font_size(use_monospace) * 2 + r.mode = Renderer.Mode.ITEMS + r.setup_object(m.result) + return r + MessageParser.Kind.TILE: + var r: Renderer = RENDERER.instantiate() + r.get_node("SubViewport").size = Vector2i.ONE * font_size(use_monospace) * 2 + r.mode = Renderer.Mode.TILES + r.setup_object(m.result) + return r + MessageParser.Kind.TEXT: + return build_label(m.result, use_monospace) + return null diff --git a/client/gui/overlays/popup_message/server_message.tscn b/client/gui/overlays/popup_message/server_message.tscn index 255c5e56..40feada1 100644 --- a/client/gui/overlays/popup_message/server_message.tscn +++ b/client/gui/overlays/popup_message/server_message.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=8 format=3 uid="uid://dq61p3a8og2b6"] +[gd_scene load_steps=5 format=3 uid="uid://dq61p3a8og2b6"] [ext_resource type="Shader" uid="uid://cwldxegcj55if" path="res://gui/resources/shaders/blur_mix.gdshader" id="1_qv8ew"] [ext_resource type="Script" uid="uid://dfgwh7x7sqc21" path="res://gui/overlays/popup_message/server_message.gd" id="2_csqo8"] -[ext_resource type="FontFile" uid="uid://bk704sc5gkrb3" path="res://gui/resources/fonts/font-azaret-mono.woff2" id="3_dw20j"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_q3bbd"] shader = ExtResource("1_qv8ew") @@ -19,35 +18,27 @@ corner_radius_top_right = 16 corner_radius_bottom_right = 16 corner_radius_bottom_left = 16 -[sub_resource type="FontVariation" id="FontVariation_qfltj"] -resource_local_to_scene = true -base_font = ExtResource("3_dw20j") -variation_opentype = { -2003265652: 400 -} - -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_3rgop"] -content_margin_left = 32.0 -content_margin_top = 8.0 -content_margin_right = 32.0 -content_margin_bottom = 8.0 - [node name="ServerMessage" type="PanelContainer"] material = SubResource("ShaderMaterial_q3bbd") +offset_right = 210.0 +offset_bottom = 35.0 size_flags_horizontal = 4 size_flags_vertical = 0 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_vq4dg") script = ExtResource("2_csqo8") -[node name="CenterContainer" type="CenterContainer" parent="."] +[node name="CenterContainer" type="MarginContainer" parent="."] layout_mode = 2 mouse_filter = 2 +theme_override_constants/margin_left = 32 +theme_override_constants/margin_top = 8 +theme_override_constants/margin_right = 32 +theme_override_constants/margin_bottom = 8 -[node name="Label" type="Label" parent="CenterContainer"] +[node name="VFlowContainer" type="VFlowContainer" parent="CenterContainer"] +layout_direction = 1 layout_mode = 2 -theme_override_colors/font_color = Color(0, 0, 0, 1) -theme_override_fonts/font = SubResource("FontVariation_qfltj") -theme_override_font_sizes/font_size = 16 -theme_override_styles/normal = SubResource("StyleBoxEmpty_3rgop") -text = "Server message" +theme_override_constants/h_separation = 0 +theme_override_constants/v_separation = 0 +last_wrap_alignment = 2 diff --git a/client/message_parser.gd b/client/message_parser.gd index 64be0411..d9c08f88 100644 --- a/client/message_parser.gd +++ b/client/message_parser.gd @@ -18,7 +18,8 @@ extends Object var raw: Dictionary var kind := Kind.UNKNOWN -var result = null +var result +var game: Game enum Kind { ITEM, @@ -28,21 +29,43 @@ enum Kind { UNKNOWN } -func _init(raw_: Dictionary) -> void: +func _init(raw_: Dictionary, game_: Game) -> void: raw = raw_ - -func parse(game: Game) -> String: + game = game_ if "text" in raw: kind = Kind.TEXT result = raw["text"] elif "translation" in raw: kind = Kind.TRANSLATION # TODO: move function here - result = Global.get_message_str(raw) + var params: Array = raw.translation.params.map(MessageParser.new.bind(game)) + var unformatted := tr(raw.translation.id) + result = split_translation(unformatted, 0, params) + if result.size() == 1 && result[0].kind == Kind.TEXT: + kind = Kind.TEXT + result = result[0].result elif "tile" in raw: kind = Kind.TILE result = game.tile_names[raw["tile"]] elif "item" in raw: kind = Kind.ITEM result = game.item_names[raw["item"]] - return result + +func split_translation(msgstr: String, idx: int, params: Array) -> Array: + if msgstr.contains("{%d}" % idx): + var s := msgstr.split("{%d}" % idx, true, 1) + var l := split_translation(s[0], idx + 1, params) + if params[idx].kind == Kind.TRANSLATION: + l.append_array(params[idx].result) + else: + l.push_back(params[idx]) + var r := split_translation(s[1], idx + 1, params) + l.append_array(r) + var res := [l.front()] + for e: MessageParser in l.slice(1): + if res.back().kind == Kind.TEXT and e.kind == Kind.TEXT: + res.back().result = "%s%s" % [res.back().result, e.result] + else: + res.push_back(e) + return res + else: return [] if msgstr.is_empty() else [MessageParser.new({"text": msgstr}, game)] |