From 84c8d6ef693efbd8e071ed641ff14fffb61e123e Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sat, 1 Feb 2020 15:04:37 -0500 Subject: [PATCH] Update and improve GUI demos --- gui/drag_and_drop/drag_and_drop.tscn | 20 ++-- gui/drag_and_drop/drag_drop_script.gd | 2 - gui/input_mapping/controls.gd | 98 +++++++++--------- gui/input_mapping/controls.tscn | 81 ++++++--------- gui/rich_text_bbcode/rich_text_bbcode.gd | 2 - gui/rich_text_bbcode/rich_text_bbcode.tscn | 10 +- gui/translation/controls.gd | 8 -- gui/translation/controls.tscn | 53 ---------- gui/translation/noto.fnt | Bin 67428 -> 0 bytes gui/translation/project.godot | 2 +- .../{main.gd => translation_demo.gd} | 6 +- .../{main.tscn => translation_demo.tscn} | 32 +++--- 12 files changed, 119 insertions(+), 195 deletions(-) delete mode 100644 gui/translation/controls.gd delete mode 100644 gui/translation/controls.tscn delete mode 100644 gui/translation/noto.fnt rename gui/translation/{main.gd => translation_demo.gd} (90%) rename gui/translation/{main.tscn => translation_demo.tscn} (72%) diff --git a/gui/drag_and_drop/drag_and_drop.tscn b/gui/drag_and_drop/drag_and_drop.tscn index 2fc24839..f8aa820c 100644 --- a/gui/drag_and_drop/drag_and_drop.tscn +++ b/gui/drag_and_drop/drag_and_drop.tscn @@ -2,7 +2,7 @@ [ext_resource path="res://drag_drop_script.gd" type="Script" id=1] -[node name="Control" type="Control"] +[node name="DragAndDrop" type="Control"] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 @@ -18,6 +18,15 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="Information" type="Label" parent="."] +margin_left = 250.0 +margin_top = 140.0 +margin_right = 761.0 +margin_bottom = 154.0 +size_flags_horizontal = 2 +size_flags_vertical = 0 +text = "Drag colors from button to button, or change button colors and drag them again." + [node name="ColorPickerButton0" type="ColorPickerButton" parent="."] margin_left = 304.0 margin_top = 193.0 @@ -107,12 +116,3 @@ size_flags_horizontal = 2 size_flags_vertical = 2 color = Color( 0, 0, 0.178211, 1 ) script = ExtResource( 1 ) - -[node name="Label" type="Label" parent="."] -margin_left = 250.0 -margin_top = 140.0 -margin_right = 761.0 -margin_bottom = 154.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "Drag colors from button to button, or change button colors and drag them again." diff --git a/gui/drag_and_drop/drag_drop_script.gd b/gui/drag_and_drop/drag_drop_script.gd index 35a8ef86..7845e239 100644 --- a/gui/drag_and_drop/drag_drop_script.gd +++ b/gui/drag_and_drop/drag_drop_script.gd @@ -1,7 +1,5 @@ - extends ColorPickerButton - func get_drag_data(_pos): # Use another colorpicker as drag preview var cpb = ColorPickerButton.new() diff --git a/gui/input_mapping/controls.gd b/gui/input_mapping/controls.gd index fa6f89cf..dc5c3431 100644 --- a/gui/input_mapping/controls.gd +++ b/gui/input_mapping/controls.gd @@ -11,18 +11,62 @@ extends Control # action and the node, e.g.: # button.connect("pressed", self, "wait_for_input", [ button, action ]) -# Constants const INPUT_ACTIONS = [ "move_up", "move_down", "move_left", "move_right", "jump" ] const CONFIG_FILE = "user://input.cfg" -# Member variables var action # To register the action the UI is currently handling var button # Button node corresponding to the above action +onready var bindings = $Bindings +onready var contextual_help = $ContextualHelp + +func _ready(): + # Load config if existing, if not it will be generated with default values + load_config() + # Initialise each button with the default key binding from InputMap + for action in INPUT_ACTIONS: + # We assume that the key binding that we want is the first one (0), if there are several + var input_event = InputMap.get_action_list(action)[0] + # See note at the beginning of the script + var button = bindings.get_node(action).get_node("Button") + button.text = OS.get_scancode_string(input_event.scancode) + button.connect("pressed", self, "wait_for_input", [action]) + + # Do not start processing input until a button is pressed + set_process_input(false) + + +# Input management +func _input(event): + # Handle the first pressed key + if event is InputEventKey: + # Register the event as handled and stop polling + get_tree().set_input_as_handled() + set_process_input(false) + # Reinitialise the contextual help label + contextual_help.text = "Click a key binding to reassign it, or press the Cancel action." + if not event.is_action("ui_cancel"): + # Display the string corresponding to the pressed key + var scancode = OS.get_scancode_string(event.scancode) + button.text = scancode + # Start by removing previously key binding(s) + for old_event in InputMap.get_action_list(action): + InputMap.action_erase_event(action, old_event) + # Add the new key binding + InputMap.action_add_event(action, event) + save_to_config("input", action, scancode) + + +func wait_for_input(action_bind): + action = action_bind + # See note at the beginning of the script + button = bindings.get_node(action).get_node("Button") + contextual_help.text = "Press a key to assign to the '" + action + "' action." + set_process_input(true) + # Load/save input mapping to a config file # Changes done while testing the demo will be persistent, saved to CONFIG_FILE - func load_config(): var config = ConfigFile.new() var err = config.load(CONFIG_FILE) @@ -48,7 +92,7 @@ func load_config(): func save_to_config(section, key, value): - """Helper function to redefine a parameter in the settings file""" + # Helper function to redefine a parameter in the settings file. var config = ConfigFile.new() var err = config.load(CONFIG_FILE) if err: @@ -56,49 +100,3 @@ func save_to_config(section, key, value): else: config.set_value(section, key, value) config.save(CONFIG_FILE) - - -# Input management - -func wait_for_input(action_bind): - action = action_bind - # See note at the beginning of the script - button = get_node("bindings").get_node(action).get_node("Button") - get_node("contextual_help").text = "Press a key to assign to the '" + action + "' action." - set_process_input(true) - - -func _input(event): - # Handle the first pressed key - if event is InputEventKey: - # Register the event as handled and stop polling - get_tree().set_input_as_handled() - set_process_input(false) - # Reinitialise the contextual help label - get_node("contextual_help").text = "Click a key binding to reassign it, or press the Cancel action." - if not event.is_action("ui_cancel"): - # Display the string corresponding to the pressed key - var scancode = OS.get_scancode_string(event.scancode) - button.text = scancode - # Start by removing previously key binding(s) - for old_event in InputMap.get_action_list(action): - InputMap.action_erase_event(action, old_event) - # Add the new key binding - InputMap.action_add_event(action, event) - save_to_config("input", action, scancode) - - -func _ready(): - # Load config if existing, if not it will be generated with default values - load_config() - # Initialise each button with the default key binding from InputMap - for action in INPUT_ACTIONS: - # We assume that the key binding that we want is the first one (0), if there are several - var input_event = InputMap.get_action_list(action)[0] - # See note at the beginning of the script - var button = get_node("bindings").get_node(action).get_node("Button") - button.text = OS.get_scancode_string(input_event.scancode) - button.connect("pressed", self, "wait_for_input", [action]) - - # Do not start processing input until a button is pressed - set_process_input(false) diff --git a/gui/input_mapping/controls.tscn b/gui/input_mapping/controls.tscn index b3fdef14..21b9d802 100644 --- a/gui/input_mapping/controls.tscn +++ b/gui/input_mapping/controls.tscn @@ -2,7 +2,7 @@ [ext_resource path="res://controls.gd" type="Script" id=1] -[node name="controls_ui" type="Control"] +[node name="Controls" type="Control"] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 @@ -19,7 +19,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="contextual_help" type="Label" parent="."] +[node name="ContextualHelp" type="Label" parent="."] margin_left = 130.0 margin_top = 100.0 margin_right = 533.0 @@ -31,26 +31,19 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="bindings" type="Control" parent="."] -margin_left = 80.0 -margin_top = 100.0 -margin_right = 120.0 -margin_bottom = 140.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="move_up" type="Control" parent="bindings"] -margin_left = 50.0 -margin_top = 50.0 -margin_right = 90.0 -margin_bottom = 90.0 +[node name="Bindings" type="VBoxContainer" parent="."] +margin_left = 150.0 +margin_top = 150.0 +margin_right = 350.0 +margin_bottom = 450.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="Label" type="Label" parent="bindings/move_up"] +[node name="move_up" type="Control" parent="Bindings"] +size_flags_horizontal = 2 +size_flags_vertical = 2 + +[node name="Label" type="Label" parent="Bindings/move_up"] margin_left = 5.0 margin_top = 8.0 margin_right = 45.0 @@ -59,7 +52,7 @@ size_flags_horizontal = 2 size_flags_vertical = 0 text = "Up" -[node name="Button" type="Button" parent="bindings/move_up"] +[node name="Button" type="Button" parent="Bindings/move_up"] margin_left = 84.0 margin_top = -1.0 margin_right = 144.0 @@ -67,15 +60,13 @@ margin_bottom = 29.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="move_down" type="Control" parent="bindings"] -margin_left = 50.0 -margin_top = 100.0 -margin_right = 90.0 -margin_bottom = 140.0 +[node name="move_down" type="Control" parent="Bindings"] +margin_top = 60.0 +margin_bottom = 60.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="Label" type="Label" parent="bindings/move_down"] +[node name="Label" type="Label" parent="Bindings/move_down"] margin_left = 5.0 margin_top = 8.0 margin_right = 45.0 @@ -84,7 +75,7 @@ size_flags_horizontal = 2 size_flags_vertical = 0 text = "Down" -[node name="Button" type="Button" parent="bindings/move_down"] +[node name="Button" type="Button" parent="Bindings/move_down"] margin_left = 84.0 margin_top = -1.0 margin_right = 144.0 @@ -92,15 +83,13 @@ margin_bottom = 29.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="move_left" type="Control" parent="bindings"] -margin_left = 50.0 -margin_top = 150.0 -margin_right = 90.0 -margin_bottom = 190.0 +[node name="move_left" type="Control" parent="Bindings"] +margin_top = 120.0 +margin_bottom = 120.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="Label" type="Label" parent="bindings/move_left"] +[node name="Label" type="Label" parent="Bindings/move_left"] margin_left = 5.0 margin_top = 8.0 margin_right = 45.0 @@ -109,7 +98,7 @@ size_flags_horizontal = 2 size_flags_vertical = 0 text = "Left" -[node name="Button" type="Button" parent="bindings/move_left"] +[node name="Button" type="Button" parent="Bindings/move_left"] margin_left = 84.0 margin_top = -1.0 margin_right = 144.0 @@ -117,15 +106,13 @@ margin_bottom = 29.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="move_right" type="Control" parent="bindings"] -margin_left = 50.0 -margin_top = 200.0 -margin_right = 90.0 -margin_bottom = 240.0 +[node name="move_right" type="Control" parent="Bindings"] +margin_top = 180.0 +margin_bottom = 180.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="Label" type="Label" parent="bindings/move_right"] +[node name="Label" type="Label" parent="Bindings/move_right"] margin_left = 5.0 margin_top = 8.0 margin_right = 45.0 @@ -134,7 +121,7 @@ size_flags_horizontal = 2 size_flags_vertical = 0 text = "Right" -[node name="Button" type="Button" parent="bindings/move_right"] +[node name="Button" type="Button" parent="Bindings/move_right"] margin_left = 84.0 margin_top = -1.0 margin_right = 144.0 @@ -142,15 +129,13 @@ margin_bottom = 29.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="jump" type="Control" parent="bindings"] -margin_left = 50.0 -margin_top = 250.0 -margin_right = 90.0 -margin_bottom = 290.0 +[node name="jump" type="Control" parent="Bindings"] +margin_top = 240.0 +margin_bottom = 240.0 size_flags_horizontal = 2 size_flags_vertical = 2 -[node name="Label" type="Label" parent="bindings/jump"] +[node name="Label" type="Label" parent="Bindings/jump"] margin_left = 5.0 margin_top = 8.0 margin_right = 45.0 @@ -159,7 +144,7 @@ size_flags_horizontal = 2 size_flags_vertical = 0 text = "Jump" -[node name="Button" type="Button" parent="bindings/jump"] +[node name="Button" type="Button" parent="Bindings/jump"] margin_left = 84.0 margin_top = -1.0 margin_right = 144.0 diff --git a/gui/rich_text_bbcode/rich_text_bbcode.gd b/gui/rich_text_bbcode/rich_text_bbcode.gd index ca172d9e..da0dfa25 100644 --- a/gui/rich_text_bbcode/rich_text_bbcode.gd +++ b/gui/rich_text_bbcode/rich_text_bbcode.gd @@ -1,7 +1,5 @@ - extends Panel - func _on_RichTextLabel_meta_clicked(meta): var err = OS.shell_open(meta) if (err == OK): diff --git a/gui/rich_text_bbcode/rich_text_bbcode.tscn b/gui/rich_text_bbcode/rich_text_bbcode.tscn index 03db56ad..ed1f1e32 100644 --- a/gui/rich_text_bbcode/rich_text_bbcode.tscn +++ b/gui/rich_text_bbcode/rich_text_bbcode.tscn @@ -22,7 +22,7 @@ font_data = ExtResource( 4 ) size = 20 font_data = ExtResource( 5 ) -[node name="Panel" type="Panel"] +[node name="RichTextBBCode" type="Panel"] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 @@ -55,20 +55,24 @@ custom_fonts/normal_font = SubResource( 4 ) bbcode_enabled = true bbcode_text = "[b][u]Rich Text Test[/u][/b] -RichTextLabel is a flexible way of adding text to your game, with support for [i]italics[/i], [b]bold[/b] and [i][b]both[/b][/i]. [u]Underline[/u] works too. +RichTextLabel is a flexible way of adding text to your game, with support for [i]italics[/i], [b]bold[/b] and [i][b]both[/b][/i]. + [u]Underline[/u] works too, including with [u][i]italics[/i][/u], [u][b]bold[/b][/u] and [u][i][b]both[/b][/i][/u]. It is also possible to include [img]res://unicorn_icon.png[/img] custom images, as well as [color=aqua][url=https://godotengine.org]custom URLs[/url][/color]. Left alignment is default,[center]but center alignment is supported,[/center][right]as well as right alignment.[/right] + [fill]Fill alignment is also supported, and allows writing very long text that will end up fitting the horizontal space entirely with words of joy.[/fill] For full reference, [color=aqua][url=https://docs.godotengine.org/en/latest/tutorials/gui/bbcode_in_richtextlabel.html]check the documentation.[/url][/color] " text = "Rich Text Test -RichTextLabel is a flexible way of adding text to your game, with support for italics, bold and both. Underline works too. +RichTextLabel is a flexible way of adding text to your game, with support for italics, bold and both. + Underline works too, including with italics, bold and both. It is also possible to include custom images, as well as custom URLs. Left alignment is default,but center alignment is supported,as well as right alignment. + Fill alignment is also supported, and allows writing very long text that will end up fitting the horizontal space entirely with words of joy. For full reference, check the documentation. diff --git a/gui/translation/controls.gd b/gui/translation/controls.gd deleted file mode 100644 index ae33c07d..00000000 --- a/gui/translation/controls.gd +++ /dev/null @@ -1,8 +0,0 @@ - -extends Panel - -func _on_back_pressed(): - var scene = load("res://main.tscn") - var si = scene.instance() - get_parent().add_child(si) - queue_free() diff --git a/gui/translation/controls.tscn b/gui/translation/controls.tscn deleted file mode 100644 index c46f056b..00000000 --- a/gui/translation/controls.tscn +++ /dev/null @@ -1,53 +0,0 @@ -[gd_scene load_steps=3 format=2] - -[ext_resource path="res://controls.gd" type="Script" id=1] -[ext_resource path="res://flag_uk.png" type="Texture" id=2] - -[node name="Panel" type="Panel"] -anchor_right = 1.0 -anchor_bottom = 1.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 -script = ExtResource( 1 ) -__meta__ = { -"__editor_plugin_screen__": "2D" -} - -[node name="Label" type="Label" parent="."] -margin_left = 175.0 -margin_top = 118.0 -margin_right = 328.0 -margin_bottom = 132.0 -size_flags_horizontal = 2 -size_flags_vertical = 0 -text = "KEY_HELLO" -align = 1 - -[node name="Button" type="Button" parent="."] -margin_left = 166.0 -margin_top = 178.0 -margin_right = 335.0 -margin_bottom = 199.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 -text = "KEY_PUSH" - -[node name="TextureFrame" type="TextureRect" parent="."] -margin_left = 377.0 -margin_top = 118.0 -margin_right = 505.0 -margin_bottom = 203.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 -texture = ExtResource( 2 ) - -[node name="back" type="Button" parent="."] -margin_left = 26.0 -margin_top = 20.0 -margin_right = 150.0 -margin_bottom = 44.0 -size_flags_horizontal = 2 -size_flags_vertical = 2 -text = "<- back" - -[connection signal="pressed" from="back" to="." method="_on_back_pressed"] diff --git a/gui/translation/noto.fnt b/gui/translation/noto.fnt deleted file mode 100644 index ac206a6374d8e4116f843cb731f2f3ee6c8cdcc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67428 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