From 6a325fb3a5bffa4936bc522fc619b38e89f0dae2 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 4 Aug 2020 13:13:08 +0200 Subject: [PATCH] Add a GUI theming override demo Overriding theme items is a common point of confusion. This demo should hopefully make it easier to understand. In the future, we could extend this demo to include things like theme switching as it's a common need in non-game applications. --- gui/theming_override/README.md | 11 ++ gui/theming_override/icon.png | Bin 0 -> 3101 bytes gui/theming_override/icon.png.import | 34 ++++++ gui/theming_override/project.godot | 34 ++++++ .../screenshots/theming_override.png | Bin 0 -> 6543 bytes .../screenshots/theming_override.png.import | 34 ++++++ gui/theming_override/test.gd | 69 ++++++++++++ gui/theming_override/test.tscn | 105 ++++++++++++++++++ 8 files changed, 287 insertions(+) create mode 100644 gui/theming_override/README.md create mode 100644 gui/theming_override/icon.png create mode 100644 gui/theming_override/icon.png.import create mode 100644 gui/theming_override/project.godot create mode 100644 gui/theming_override/screenshots/theming_override.png create mode 100644 gui/theming_override/screenshots/theming_override.png.import create mode 100644 gui/theming_override/test.gd create mode 100644 gui/theming_override/test.tscn diff --git a/gui/theming_override/README.md b/gui/theming_override/README.md new file mode 100644 index 00000000..39ad5c3e --- /dev/null +++ b/gui/theming_override/README.md @@ -0,0 +1,11 @@ +# GUI Theming Override Demo + +Demonstrates how to override GUI colors and styleboxes at runtime. + +Language: GDScript + +Renderer: GLES 2 + +## Screenshots + +![Screenshot](screenshots/theming_override.png) diff --git a/gui/theming_override/icon.png b/gui/theming_override/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..417b0b8783278d91935202d6b33ff1ebca04247e GIT binary patch literal 3101 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 literal 0 HcmV?d00001 diff --git a/gui/theming_override/screenshots/theming_override.png.import b/gui/theming_override/screenshots/theming_override.png.import new file mode 100644 index 00000000..5efc11dc --- /dev/null +++ b/gui/theming_override/screenshots/theming_override.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/theming_override.png-fd290b6e357e98ef694c719db436e418.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://screenshots/theming_override.png" +dest_files=[ "res://.import/theming_override.png-fd290b6e357e98ef694c719db436e418.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/gui/theming_override/test.gd b/gui/theming_override/test.gd new file mode 100644 index 00000000..e157d3e9 --- /dev/null +++ b/gui/theming_override/test.gd @@ -0,0 +1,69 @@ +extends Control + +# This script demonstrates how to alter StyleBoxes at runtime. +# Custom theme item properties aren't considered Object properties per se. +# This means that you should use `add_stylebox_override("normal", ...)` +# instead of `set("custom_styles/normal", ...)`. + +onready var label = $VBoxContainer/Label +onready var button = $VBoxContainer/Button +onready var button2 = $VBoxContainer/Button2 +onready var reset_all_button = $VBoxContainer/ResetAllButton + + +func _ready(): + # Focus the first button automatically for keyboard/controller-friendly navigation. + button.grab_focus() + + +func _on_button_pressed(): + # We have to modify the normal, hover and pressed styleboxes all at once + # to get a correct appearance when the button is hovered or pressed. + # We can't use a single StyleBox for all of them as these have different + # background colors. + var new_stylebox_normal = button.get_stylebox("normal").duplicate() + new_stylebox_normal.border_color = Color(1, 1, 0) + var new_stylebox_hover = button.get_stylebox("hover").duplicate() + new_stylebox_hover.border_color = Color(1, 1, 0) + var new_stylebox_pressed = button.get_stylebox("pressed").duplicate() + new_stylebox_pressed.border_color = Color(1, 1, 0) + + button.add_stylebox_override("normal", new_stylebox_normal) + button.add_stylebox_override("hover", new_stylebox_hover) + button.add_stylebox_override("pressed", new_stylebox_pressed) + + label.add_color_override("font_color", Color(1, 1, 0.5)) + + +func _on_button2_pressed(): + var new_stylebox_normal = button2.get_stylebox("normal").duplicate() + new_stylebox_normal.border_color = Color(0, 1, 0.5) + var new_stylebox_hover = button2.get_stylebox("hover").duplicate() + new_stylebox_hover.border_color = Color(0, 1, 0.5) + var new_stylebox_pressed = button2.get_stylebox("pressed").duplicate() + new_stylebox_pressed.border_color = Color(0, 1, 0.5) + + button2.add_stylebox_override("normal", new_stylebox_normal) + button2.add_stylebox_override("hover", new_stylebox_hover) + button2.add_stylebox_override("pressed", new_stylebox_pressed) + + label.add_color_override("font_color", Color(0.5, 1, 0.75)) + + +func _on_reset_all_button_pressed(): + # Resetting a theme override is done by setting the property to: + # - `null` for fonts, icons, styleboxes, and shaders. + # - `0` for constants. + # - Colors must be reset manually by adding the previous color value as an override. + button.add_stylebox_override("normal", null) + button.add_stylebox_override("hover", null) + button.add_stylebox_override("pressed", null) + + button2.add_stylebox_override("normal", null) + button2.add_stylebox_override("hover", null) + button2.add_stylebox_override("pressed", null) + + # If you don't have any references to the previous color value, + # you can instance a node at runtime to get this value. + var default_label_color = Label.new().get_color("font_color") + label.add_color_override("font_color", default_label_color) diff --git a/gui/theming_override/test.tscn b/gui/theming_override/test.tscn new file mode 100644 index 00000000..32056863 --- /dev/null +++ b/gui/theming_override/test.tscn @@ -0,0 +1,105 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://test.gd" type="Script" id=1] + +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 0.16, 0.678, 1, 0.12549 ) + +[sub_resource type="StyleBoxFlat" id=2] +bg_color = Color( 0.266667, 0.266667, 0.266667, 1 ) +border_width_left = 3 +border_width_top = 3 +border_width_right = 3 +border_width_bottom = 3 +border_color = Color( 0.4, 0.4, 0.4, 1 ) +border_blend = true + +[sub_resource type="StyleBoxFlat" id=3] +content_margin_left = 20.0 +content_margin_right = 20.0 +content_margin_top = 16.0 +content_margin_bottom = 16.0 +bg_color = Color( 0.2, 0.2, 0.2, 1 ) +border_width_left = 3 +border_width_top = 3 +border_width_right = 3 +border_width_bottom = 3 +border_color = Color( 0.333333, 0.333333, 0.333333, 1 ) +border_blend = true + +[sub_resource type="StyleBoxFlat" id=4] +bg_color = Color( 0.133333, 0.133333, 0.133333, 1 ) +border_width_left = 3 +border_width_top = 3 +border_width_right = 3 +border_width_bottom = 3 +border_color = Color( 0.266667, 0.266667, 0.266667, 1 ) +border_blend = true + +[sub_resource type="Theme" id=5] +Button/colors/font_color = Color( 0.88, 0.88, 0.88, 1 ) +Button/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) +Button/colors/font_color_hover = Color( 0.94, 0.94, 0.94, 1 ) +Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) +Button/constants/hseparation = 2 +Button/fonts/font = null +Button/styles/disabled = null +Button/styles/focus = SubResource( 1 ) +Button/styles/hover = SubResource( 2 ) +Button/styles/normal = SubResource( 3 ) +Button/styles/pressed = SubResource( 4 ) + +[node name="Control" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +theme = SubResource( 5 ) +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -75.5 +margin_top = -157.0 +margin_right = 75.5 +margin_bottom = 89.0 +custom_constants/separation = 20 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Label" type="Label" parent="VBoxContainer"] +margin_right = 151.0 +margin_bottom = 48.0 +rect_min_size = Vector2( 0, 48 ) +text = "GUI Theming Overrides" +align = 1 +valign = 1 + +[node name="Button" type="Button" parent="VBoxContainer"] +margin_top = 68.0 +margin_right = 151.0 +margin_bottom = 114.0 +text = "Click Me" + +[node name="Button2" type="Button" parent="VBoxContainer"] +margin_top = 134.0 +margin_right = 151.0 +margin_bottom = 180.0 +text = "Click Me" + +[node name="ResetAllButton" type="Button" parent="VBoxContainer"] +margin_top = 200.0 +margin_right = 151.0 +margin_bottom = 246.0 +text = "Reset All" +__meta__ = { +"_edit_use_anchors_": false +} +[connection signal="pressed" from="VBoxContainer/Button" to="." method="_on_button_pressed"] +[connection signal="pressed" from="VBoxContainer/Button2" to="." method="_on_button2_pressed"] +[connection signal="pressed" from="VBoxContainer/ResetAllButton" to="." method="_on_reset_all_button_pressed"]