Add Multiple Windows Demo (#1103)

This commit is contained in:
Vissa
2025-10-09 01:00:22 +03:00
committed by GitHub
parent 7d73b8c4cb
commit a01005f397
38 changed files with 1091 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
# Window Management
A demo showing all [`Window`](https://docs.godotengine.org/en/stable/classes/class_window.html) classes and their use within the main window.
It includes:
- Embedding/unembedding subwindows.
- Using a transparent window.
- Adding physical objects to new windows.
- Showcase of all Dialog Windows.
- Showcase of all Popup Windows.
- Adding elements to a Popup Menu.
- Adding an icon to the system tray.
Language: GDScript
Renderer: Compatbility
## Screenshots
![Screenshot](screenshots/screenshot.webp)

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cehd300ehf1vw"
path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.webp"
dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@@ -0,0 +1,31 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Multiple Windows Demo"
config/description="A demo showing all Window classes and their use within the main window."
run/main_scene="res://scenes/main_scene.tscn"
config/features=PackedStringArray("4.5", "GL Compatibility")
run/low_processor_mode=true
config/icon="res://icon.webp"
[display]
window/size/viewport_width=650
window/size/viewport_height=650
window/stretch/mode="canvas_items"
window/stretch/aspect="expand"
window/per_pixel_transparency/allowed=true
[rendering]
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"

View File

@@ -0,0 +1,7 @@
[gd_scene format=3 uid="uid://cudrukovmha7p"]
[node name="AcceptDialog" type="AcceptDialog"]
initial_position = 2
size = Vector2i(277, 100)
visible = true
dialog_text = "This is an AcceptDialog window"

View File

@@ -0,0 +1,7 @@
[gd_scene format=3 uid="uid://1nswovajdv3n"]
[node name="ConfirmationDialog" type="ConfirmationDialog"]
initial_position = 2
size = Vector2i(310, 100)
visible = true
dialog_text = "This is a ConfimationDialog window"

View File

@@ -0,0 +1,29 @@
extends BaseButton
enum Behavior {
ENABLE_OTHERS_WHEN_ENABLED,
ENABLE_OTHERS_WHEN_DISABLED,
}
@export var behavior: Behavior = Behavior.ENABLE_OTHERS_WHEN_ENABLED
@export var others: Array[BaseButton] = []
func _ready() -> void:
var others_disabled: bool
if behavior == Behavior.ENABLE_OTHERS_WHEN_ENABLED:
others_disabled = not button_pressed
else:
others_disabled = button_pressed
for other in others:
other.disabled = others_disabled
func _toggled(toggled_on: bool) -> void:
if behavior == Behavior.ENABLE_OTHERS_WHEN_ENABLED:
for other in others:
other.disabled = not toggled_on
else:
for other in others:
other.disabled = toggled_on

View File

@@ -0,0 +1 @@
uid://b4ngyw7e2c75u

View File

@@ -0,0 +1,6 @@
extends Area2D
func _input_event(_viewport: Viewport, event: InputEvent, _shape_index: int) -> void:
if event is InputEventMouseButton:
if event.pressed:
get_window().start_drag()

View File

@@ -0,0 +1 @@
uid://d1nq2ipicit18

View File

@@ -0,0 +1,40 @@
[gd_scene load_steps=6 format=3 uid="uid://ek1fmwy87san"]
[ext_resource type="Texture2D" uid="uid://pgdemhy0xqog" path="res://scenes/draggable_window/hand.svg" id="1_y4nm8"]
[ext_resource type="Script" uid="uid://d1nq2ipicit18" path="res://scenes/draggable_window/draggable_region.gd" id="2_pflw3"]
[ext_resource type="Script" uid="uid://djnd1kuhucddh" path="res://scenes/draggable_window/sprite_polygon_passthrough.gd" id="3_20753"]
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_ghj85"]
size = Vector2(256, 256)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_cvhp1"]
size = Vector2(128, 128)
[node name="DraggableWindow" type="Window"]
transparent_bg = true
physics_object_picking = true
oversampling_override = 1.0
size = Vector2i(128, 128)
unresizable = true
borderless = true
always_on_top = true
transparent = true
[node name="BG" type="Sprite2D" parent="."]
visible = false
texture = SubResource("PlaceholderTexture2D_ghj85")
centered = false
[node name="Icon" type="Sprite2D" parent="."]
position = Vector2(64, 64)
texture = ExtResource("1_y4nm8")
[node name="Area2D" type="Area2D" parent="Icon"]
script = ExtResource("2_pflw3")
[node name="CollisionShape2D" type="CollisionShape2D" parent="Icon/Area2D"]
shape = SubResource("RectangleShape2D_cvhp1")
[node name="PassthroughGenerator" type="Node" parent="." node_paths=PackedStringArray("sprite")]
script = ExtResource("3_20753")
sprite = NodePath("../Icon")

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{display:inline;fill:#363D52;stroke:#212532;stroke-width:4;}
.st2{display:inline;}
.st3{fill:#FFFFFF;}
.st4{fill:#478CBF;}
.st5{fill:#414042;}
.st6{fill:#363D52;stroke:#212532;stroke-width:4;}
</style>
<g id="Layer_1" class="st0">
<path class="st1" d="M16,2h96c7.7,0,14,6.3,14,14v96c0,7.7-6.3,14-14,14H16c-7.7,0-14-6.3-14-14V16C2,8.3,8.3,2,16,2z"/>
<g transform="translate(12.322 12.322)scale(.101)" class="st2">
<path class="st3" d="M105,673v33c271.3,236,542.7,236,814,0v-33H105z"/>
<path class="st4" d="M105,673l152,14c8,0.7,13,5.3,15,14l4,67l132,10l8-61c1.3-7.3,6.3-12.3,15-15h162c8.7,2.7,13.7,7.7,15,15
l8,61l132-10l4-67c2-8.7,7-13.3,15-14l152-14V427c20-26,38.7-53,56-81c-23.3-39.3-51-75.3-83-108c-28.7,13.3-56,29-82,47
c-26.7-24.7-56-46-88-64c4.7-34,7.3-68,8-102c-39.3-18.7-80.3-32.7-123-42c-17.3,28.7-32.7,58.3-46,89c-32.7-4.7-65.3-4.7-98,0
c-13.3-30.7-28.7-60.3-46-89c-42.7,9.3-83.7,23.3-123,42c0.7,34,3.3,68,8,102c-32,18-61.3,39.3-88,64c-26-18-53.3-33.7-82-47
c-32,32.7-59.7,68.7-83,108c17.3,28,36,55,56,81V673z M105,706v39c0,276,813,276,814,0v-39l-134,12l-5,69c-1.3,6.7-6,11-14,13
l-162,11c-8,0-13.3-3.7-16-11l-10-65H446l-10,65c-2.7,7.3-8,11-16,11l-162-11c-8-2-12.7-6.3-14-13l-5-69L105,706z"/>
<path class="st3" d="M483,600c0,34,58,34,58,0v-86c0-34-58-34-58,0V600z"/>
<circle class="st3" cx="725" cy="526" r="90"/>
<circle class="st3" cx="299" cy="526" r="90"/>
</g>
<g transform="translate(12.322 12.322)scale(.101)" class="st2">
<circle class="st5" cx="307" cy="532" r="60"/>
<circle class="st5" cx="717" cy="532" r="60"/>
</g>
</g>
<g id="Layer_2" class="st0">
<g class="st2">
<path d="M112,92c0,17.7-21.5,32-48,32s-48-14.3-48-32H112z"/>
<path d="M32,92H16V52c0-4.4,3.6-8,8-8h0c4.4,0,8,3.6,8,8V92z"/>
<path d="M52,92H36V20c0-4.4,3.6-8,8-8h0c4.4,0,8,3.6,8,8V92z"/>
<path d="M72,92H56V12c0-4.4,3.6-8,8-8h0c4.4,0,8,3.6,8,8V92z"/>
<path d="M92,92H76V20c0-4.4,3.6-8,8-8h0c4.4,0,8,3.6,8,8V92z"/>
<path d="M112,92H96V40c0-4.4,3.6-8,8-8h0c4.4,0,8,3.6,8,8V92z"/>
<rect x="52" y="60" width="44" height="32"/>
</g>
</g>
<g id="Layer_2_copy">
<path class="st6" d="M104,32c-4.4,0-8,3.6-8,8v20h-4V20c0-4.4-3.6-8-8-8s-8,3.6-8,8v40h-4V12c0-4.4-3.6-8-8-8s-8,3.6-8,8v48h-4V20
c0-4.4-3.6-8-8-8s-8,3.6-8,8v72h-4V52c0-4.4-3.6-8-8-8s-8,3.6-8,8v40c0,17.7,21.5,32,48,32s48-14.3,48-32V40
C112,35.6,108.4,32,104,32z"/>
</g>
<g id="Layer_1_copy" class="st0">
<path class="st1" d="M16,2h96c7.7,0,14,6.3,14,14v96c0,7.7-6.3,14-14,14H16c-7.7,0-14-6.3-14-14V16C2,8.3,8.3,2,16,2z"/>
</g>
<g id="Layer_5">
<rect x="49.9" y="74.2" class="st4" width="47.8" height="20.9"/>
<g>
<g transform="translate(12.322 12.322)scale(.101)">
<path class="st3" d="M588.9,764.8c0,23.9,40.8,23.9,40.8,0v-60.5c0-23.9-40.8-23.9-40.8,0V764.8z"/>
<circle class="st3" cx="759.2" cy="712.7" r="63.3"/>
<circle class="st3" cx="459.5" cy="712.7" r="63.3"/>
</g>
<g transform="translate(12.322 12.322)scale(.101)">
<circle class="st5" cx="465.1" cy="717" r="42.2"/>
<circle class="st5" cx="753.5" cy="717" r="42.2"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://pgdemhy0xqog"
path="res://.godot/imported/hand.svg-b2d702bcd7ae140c6ed485fe3d5b4a36.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://scenes/draggable_window/hand.svg"
dest_files=["res://.godot/imported/hand.svg-b2d702bcd7ae140c6ed485fe3d5b4a36.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@@ -0,0 +1,34 @@
extends Node
@export var sprite: Sprite2D
func generate_polygon():
# Make a bitmap out of a sprite.
var bitmap := BitMap.new()
bitmap.create_from_image_alpha(sprite.texture.get_image())
# Cell size in case sprite cell is used for animation.
var cell_size_x := float(bitmap.get_size().x) / sprite.hframes
var cell_size_y := float(bitmap.get_size().y) / sprite.vframes
var cell_rect: Rect2 = Rect2(cell_size_x * sprite.frame_coords.x, cell_size_y * sprite.frame_coords.y, cell_size_x, cell_size_y)
# Grow bitmap to make sure every pixel will be captured.
bitmap.grow_mask(1, cell_rect)
# Generate array of polygons from bitmap.
var bitmap_polygons: Array[PackedVector2Array] = bitmap.opaque_to_polygons(cell_rect, 1.0)
var polygon = PackedVector2Array()
# Offset to position polygon correctly in relation of sprite to a window.
var offset: Vector2 = sprite.position + sprite.offset
if sprite.centered:
offset -= Vector2(cell_size_x, cell_size_y) / 2
# First point is used to connect multiple polygons into one big polygon.
var first_point: Vector2 = bitmap_polygons[0][0]
# Uniting all polygons into polygon for window to use.
for bitmap_polygon: PackedVector2Array in bitmap_polygons:
for point: Vector2 in bitmap_polygon:
polygon.append(point + offset)
polygon.append(first_point)
polygon.append(first_point)
# Apply passthrough mask to the window.
get_window().mouse_passthrough_polygon = polygon

View File

@@ -0,0 +1 @@
uid://djnd1kuhucddh

View File

@@ -0,0 +1,6 @@
[gd_scene format=3 uid="uid://dx84v67isxyjv"]
[node name="FileDialog" type="FileDialog"]
initial_position = 2
size = Vector2i(700, 400)
visible = true

View File

@@ -0,0 +1,187 @@
extends Control
@onready var window: Window = $Window
@onready var draggable_window: Window = $DraggableWindow
@onready var file_dialog: FileDialog = $FileDialog
@onready var file_dialog_output: TextEdit = $HBoxContainer/VBoxContainer2/FileDialogOutput
@onready var accept_dialog: AcceptDialog = $AcceptDialog
@onready var accept_dialog_output: TextEdit = $HBoxContainer/VBoxContainer2/AcceptOutput
@onready var confirmation_dialog: ConfirmationDialog = $ConfirmationDialog
@onready var confirmation_dialog_output: TextEdit = $HBoxContainer/VBoxContainer2/ConfirmationOutput
@onready var popup: Popup = $Popup
@onready var popup_menu: PopupMenu = $PopupMenu
@onready var popup_menu_output: TextEdit = $HBoxContainer/VBoxContainer3/PopupMenuOutput
@onready var popup_panel: PopupPanel = $PopupPanel
@onready var status_indicator: StatusIndicator = $StatusIndicator
func _on_embed_subwindows_toggled(toggled_on: bool) -> void:
var hidden_windows: Array[Window] = []
for child in get_children():
if child is Window and child.is_visible():
child.hide()
hidden_windows.append(child)
embed_subwindows(toggled_on)
for _window in hidden_windows:
_window.show()
func embed_subwindows(state: bool) -> void:
get_viewport().gui_embed_subwindows = state
func _on_window_button_pressed() -> void:
window.show()
window.grab_focus()
func _on_transient_window_toggled(toggled_on: bool) -> void:
window.transient = toggled_on
func _on_exclusive_window_toggled(toggled_on: bool) -> void:
window.exclusive = toggled_on
func _on_unresizable_window_toggled(toggled_on: bool) -> void:
window.unresizable = toggled_on
func _on_borderless_window_toggled(toggled_on: bool) -> void:
window.borderless = toggled_on
func _on_always_on_top_window_toggled(toggled_on: bool) -> void:
window.always_on_top = toggled_on
func _on_transparent_window_toggled(toggled_on: bool) -> void:
window.transparent = toggled_on
func _on_window_title_edit_text_changed(new_text: String) -> void:
window.title = new_text
func _on_draggable_window_button_pressed() -> void:
draggable_window.show()
draggable_window.grab_focus()
func _on_draggable_window_close_pressed() -> void:
draggable_window.hide()
func _on_bg_draggable_window_toggled(toggled_on: bool) -> void:
draggable_window.get_node("BG").visible = toggled_on
func _on_passthrough_polygon_item_selected(index: int) -> void:
match index:
0:
draggable_window.mouse_passthrough_polygon = []
1:
draggable_window.get_node("PassthroughGenerator").generate_polygon()
2:
draggable_window.mouse_passthrough_polygon = [
Vector2(16, 0), Vector2(16, 128),
Vector2(116, 128), Vector2(116, 0)]
func _on_file_dialog_button_pressed() -> void:
file_dialog.show()
func _on_file_dialog_dir_selected(dir: String) -> void:
file_dialog_output.text = "Directory Path: " + dir
func _on_file_dialog_file_selected(path: String) -> void:
file_dialog_output.text = "File Path: " + path
func _on_file_dialog_files_selected(paths: PackedStringArray) -> void:
file_dialog_output.text = "Chosen Paths: " + str(paths)
func _on_file_dialog_options_item_selected(index: int) -> void:
match index:
0:
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
1:
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILES
2:
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_DIR
3:
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_ANY
4:
file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
func _on_native_dialog_toggled(toggled_on: bool) -> void:
file_dialog.use_native_dialog = toggled_on
func _on_accept_button_text_submitted(new_text: String) -> void:
if not new_text.is_empty():
accept_dialog.add_button(new_text, false, new_text)
func _on_accept_dialog_canceled() -> void:
accept_dialog_output.text = "Cancelled"
func _on_accept_dialog_confirmed() -> void:
accept_dialog_output.text = "Accepted"
func _on_accept_dialog_custom_action(action: StringName) -> void:
accept_dialog_output.text = "Custom Action: " + action
accept_dialog.hide()
func _on_accept_button_pressed() -> void:
accept_dialog.show()
func _on_confirmation_button_pressed() -> void:
confirmation_dialog.show()
func _on_confirmation_dialog_canceled() -> void:
confirmation_dialog_output.text = "Cancelled"
func _on_confirmation_dialog_confirmed() -> void:
confirmation_dialog_output.text = "Accepted"
func show_popup(_popup: Popup):
var mouse_position
if get_viewport().gui_embed_subwindows:
mouse_position = get_global_mouse_position()
else:
mouse_position = DisplayServer.mouse_get_position()
_popup.popup(Rect2(mouse_position, _popup.size))
func _on_popup_button_pressed() -> void:
show_popup(popup)
func _on_popup_menu_button_pressed() -> void:
show_popup(popup_menu)
func _on_popup_panel_button_pressed() -> void:
show_popup(popup_panel)
func _on_popup_menu_option_pressed(option: String) -> void:
popup_menu_output.text = option + " was pressed."
func _on_status_indicator_visible_toggled(toggled_on: bool) -> void:
status_indicator.visible = toggled_on

View File

@@ -0,0 +1 @@
uid://brqixlpt4am24

View File

@@ -0,0 +1,368 @@
[gd_scene load_steps=13 format=3 uid="uid://8nmbmlqd6df6"]
[ext_resource type="Script" uid="uid://brqixlpt4am24" path="res://scenes/main_scene.gd" id="1_nwc20"]
[ext_resource type="PackedScene" uid="uid://blbehgenpldb" path="res://scenes/window/window.tscn" id="2_ldw47"]
[ext_resource type="Script" uid="uid://b4ngyw7e2c75u" path="res://scenes/disable_other.gd" id="2_psh0l"]
[ext_resource type="Script" uid="uid://evvrji8vwf5l" path="res://scenes/text_field.gd" id="3_bgndp"]
[ext_resource type="PackedScene" uid="uid://ek1fmwy87san" path="res://scenes/draggable_window/draggable_window.tscn" id="4_diw6b"]
[ext_resource type="PackedScene" uid="uid://dx84v67isxyjv" path="res://scenes/file_dialogue/file_dialog.tscn" id="5_f4o8g"]
[ext_resource type="PackedScene" uid="uid://cudrukovmha7p" path="res://scenes/accept_dialogue/accept_dialog.tscn" id="6_st8be"]
[ext_resource type="PackedScene" uid="uid://1nswovajdv3n" path="res://scenes/confimation_dialogue/confirmation_dialog.tscn" id="7_wii4q"]
[ext_resource type="PackedScene" uid="uid://p7lgllpnc8h8" path="res://scenes/popup/popup.tscn" id="8_vohc5"]
[ext_resource type="PackedScene" uid="uid://j7j6fe7plvmt" path="res://scenes/popup_menu/popup_menu.tscn" id="9_b1y32"]
[ext_resource type="PackedScene" uid="uid://dj15to28g17lb" path="res://scenes/popup_panel/popup_panel.tscn" id="10_rn47v"]
[ext_resource type="PackedScene" uid="uid://bfsfek8h27vha" path="res://scenes/status_indicator/status_indicator.tscn" id="12_cb4u3"]
[node name="MainScene" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_nwc20")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 32
alignment = 1
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
[node name="EmbedSubwindows" type="CheckButton" parent="HBoxContainer/VBoxContainer" node_paths=PackedStringArray("others")]
layout_mode = 2
button_pressed = true
text = "Embed Subwindows"
script = ExtResource("2_psh0l")
others = [NodePath("../TransparentWindow"), NodePath("../PassthroughPolygon")]
behavior = 1
[node name="HSeparator" type="HSeparator" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
[node name="WindowLabel" type="Label" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Window"
horizontal_alignment = 1
[node name="WindowButton" type="Button" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Show window"
[node name="WindowTitleEdit" type="LineEdit" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
placeholder_text = "Window's Title"
[node name="TransientWindow" type="CheckButton" parent="HBoxContainer/VBoxContainer" node_paths=PackedStringArray("others")]
layout_mode = 2
text = "Transient"
script = ExtResource("2_psh0l")
others = [NodePath("../ExclusiveWindow")]
[node name="ExclusiveWindow" type="CheckButton" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
tooltip_text = "Needs transient enabled to work."
disabled = true
text = "Exclusive
"
[node name="UnresizableWindow" type="CheckButton" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Unresizable
"
[node name="BorderlessWindow" type="CheckButton" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Borderless"
[node name="AlwaysOnTopWindow" type="CheckButton" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Always on Top"
[node name="TransparentWindow" type="CheckButton" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
tooltip_text = "Needs embed_subwindows disabled to work."
text = "Transparent
"
[node name="HSeparator2" type="HSeparator" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
[node name="WindowArea2D" type="Label" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Window with Area2D"
horizontal_alignment = 1
[node name="HBoxContainerDW" type="HBoxContainer" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
[node name="DraggableWindowButton" type="Button" parent="HBoxContainer/VBoxContainer/HBoxContainerDW"]
layout_mode = 2
size_flags_horizontal = 3
text = "Draggable window"
[node name="Close" type="Button" parent="HBoxContainer/VBoxContainer/HBoxContainerDW"]
layout_mode = 2
text = "X"
[node name="DraggableWindowExplanation" type="RichTextLabel" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/normal_font_size = 12
text = "This window uses Area2D to detect if user clicked inside of it.
Since it's Area2D, you can change it's CollisionShape2D.
But since Area2D is a Physics Object, \"Physics Object Picking\" inside of Window's properties hard to be enabled.
"
fit_content = true
[node name="BGDraggableWindow" type="CheckButton" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
tooltip_text = "Needs embed_subwindows disabled to work."
text = "Add Background"
[node name="PassthroughLabel" type="Label" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Passthrough Polygon:"
[node name="PassthroughPolygon" type="OptionButton" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
tooltip_text = "Needs embed_subwindows disabled to work."
selected = 0
item_count = 3
popup/item_0/text = "Empty"
popup/item_0/id = 0
popup/item_1/text = "Calculate via BitMap"
popup/item_1/id = 1
popup/item_2/text = "Rectangle"
popup/item_2/id = 2
[node name="VBoxContainer2" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
[node name="FileDialogLabel" type="Label" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
text = "File Dialog"
horizontal_alignment = 1
[node name="FileDialogButton" type="Button" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
text = "Show File Dialog"
[node name="FileDialogOptions" type="OptionButton" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
selected = 4
item_count = 5
popup/item_0/text = "Open File"
popup/item_0/id = 0
popup/item_1/text = "Open Files"
popup/item_1/id = 1
popup/item_2/text = "Open Folder"
popup/item_2/id = 2
popup/item_3/text = "Open Any"
popup/item_3/id = 3
popup/item_4/text = "Save"
popup/item_4/id = 4
[node name="NativeDialog" type="CheckButton" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
text = "Use Native
Dialog"
[node name="FileDialogOutput" type="TextEdit" parent="HBoxContainer/VBoxContainer2"]
custom_minimum_size = Vector2(200, 150)
layout_mode = 2
placeholder_text = "Chosen path will show up here."
editable = false
wrap_mode = 1
[node name="HSeparator" type="HSeparator" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
[node name="AcceptLabel" type="Label" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
text = "Accept Dialog"
horizontal_alignment = 1
[node name="AcceptButton" type="Button" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
text = "Show Accept Dialog"
[node name="NewButtonField" type="HBoxContainer" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
[node name="LineEdit" type="LineEdit" parent="HBoxContainer/VBoxContainer2/NewButtonField" node_paths=PackedStringArray("submit_button")]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "New button field"
script = ExtResource("3_bgndp")
submit_button = NodePath("../Submit")
[node name="Submit" type="Button" parent="HBoxContainer/VBoxContainer2/NewButtonField"]
layout_mode = 2
text = "Enter"
[node name="AcceptOutput" type="TextEdit" parent="HBoxContainer/VBoxContainer2"]
custom_minimum_size = Vector2(200, 70)
layout_mode = 2
placeholder_text = "Dialogue result will show up here."
editable = false
wrap_mode = 1
[node name="HSeparator2" type="HSeparator" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
[node name="ConfirmationLabel" type="Label" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
text = "Confirmation Dialog"
horizontal_alignment = 1
[node name="ConfirmationButton" type="Button" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
text = "Show Dialogue"
[node name="ConfirmationOutput" type="TextEdit" parent="HBoxContainer/VBoxContainer2"]
custom_minimum_size = Vector2(200, 35)
layout_mode = 2
placeholder_text = "Confirmation Result"
editable = false
wrap_mode = 1
[node name="VBoxContainer3" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
[node name="PopupLabel" type="Label" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
text = "Popup"
horizontal_alignment = 1
[node name="PopupButton" type="Button" parent="HBoxContainer/VBoxContainer3"]
custom_minimum_size = Vector2(150, 85)
layout_mode = 2
text = "Show Popup"
[node name="PopupDescription" type="RichTextLabel" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
theme_override_font_sizes/normal_font_size = 12
theme_override_font_sizes/mono_font_size = 12
bbcode_enabled = true
text = "Popup hiding on mouse exit is handled by via [code]mouse_exited[/code] signal"
fit_content = true
[node name="HSeparator" type="HSeparator" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
[node name="PopupMenuLabel" type="Label" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
text = "Popup"
horizontal_alignment = 1
[node name="PopupMenuButton" type="Button" parent="HBoxContainer/VBoxContainer3"]
custom_minimum_size = Vector2(150, 85)
layout_mode = 2
text = "Show Popup"
[node name="PopupMenuOutput" type="TextEdit" parent="HBoxContainer/VBoxContainer3"]
custom_minimum_size = Vector2(0, 100)
layout_mode = 2
placeholder_text = "Pressed option will show up here."
editable = false
wrap_mode = 1
[node name="HSeparator2" type="HSeparator" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
[node name="PopupPanelLabel" type="Label" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
text = "Popup"
horizontal_alignment = 1
[node name="PopupPanelButton" type="Button" parent="HBoxContainer/VBoxContainer3"]
custom_minimum_size = Vector2(150, 85)
layout_mode = 2
text = "Show Popup"
[node name="HSeparator3" type="HSeparator" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
[node name="StatusIndicatorLabel" type="Label" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
text = "Status Indicator"
horizontal_alignment = 1
[node name="StatusIndicatorVisible" type="CheckButton" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
button_pressed = true
text = "Visible Tray Icon"
[node name="OSLimitation" type="RichTextLabel" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
theme_override_font_sizes/normal_font_size = 12
text = "Only works on Windows and macOS"
fit_content = true
[node name="Window" parent="." instance=ExtResource("2_ldw47")]
visible = false
[node name="DraggableWindow" parent="." instance=ExtResource("4_diw6b")]
visible = false
[node name="FileDialog" parent="." instance=ExtResource("5_f4o8g")]
visible = false
access = 2
[node name="AcceptDialog" parent="." instance=ExtResource("6_st8be")]
visible = false
[node name="ConfirmationDialog" parent="." instance=ExtResource("7_wii4q")]
visible = false
[node name="Popup" parent="." instance=ExtResource("8_vohc5")]
visible = false
[node name="PopupMenu" parent="." instance=ExtResource("9_b1y32")]
visible = false
unfocusable = false
[node name="PopupPanel" parent="." instance=ExtResource("10_rn47v")]
visible = false
[node name="StatusIndicator" parent="." instance=ExtResource("12_cb4u3")]
tooltip = "Multiple Windows Demo"
[connection signal="toggled" from="HBoxContainer/VBoxContainer/EmbedSubwindows" to="." method="_on_embed_subwindows_toggled"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer/WindowButton" to="." method="_on_window_button_pressed"]
[connection signal="text_changed" from="HBoxContainer/VBoxContainer/WindowTitleEdit" to="." method="_on_window_title_edit_text_changed"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer/TransientWindow" to="." method="_on_transient_window_toggled"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer/ExclusiveWindow" to="." method="_on_exclusive_window_toggled"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer/UnresizableWindow" to="." method="_on_unresizable_window_toggled"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer/BorderlessWindow" to="." method="_on_borderless_window_toggled"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer/AlwaysOnTopWindow" to="." method="_on_always_on_top_window_toggled"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer/TransparentWindow" to="." method="_on_transparent_window_toggled"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer/HBoxContainerDW/DraggableWindowButton" to="." method="_on_draggable_window_button_pressed"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer/HBoxContainerDW/Close" to="." method="_on_draggable_window_close_pressed"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer/BGDraggableWindow" to="." method="_on_bg_draggable_window_toggled"]
[connection signal="item_selected" from="HBoxContainer/VBoxContainer/PassthroughPolygon" to="." method="_on_passthrough_polygon_item_selected"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer2/FileDialogButton" to="." method="_on_file_dialog_button_pressed"]
[connection signal="item_selected" from="HBoxContainer/VBoxContainer2/FileDialogOptions" to="." method="_on_file_dialog_options_item_selected"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer2/NativeDialog" to="." method="_on_native_dialog_toggled"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer2/AcceptButton" to="." method="_on_accept_button_pressed"]
[connection signal="text_submitted" from="HBoxContainer/VBoxContainer2/NewButtonField/LineEdit" to="." method="_on_accept_button_text_submitted"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer2/ConfirmationButton" to="." method="_on_confirmation_button_pressed"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer3/PopupButton" to="." method="_on_popup_button_pressed"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer3/PopupMenuButton" to="." method="_on_popup_menu_button_pressed"]
[connection signal="pressed" from="HBoxContainer/VBoxContainer3/PopupPanelButton" to="." method="_on_popup_panel_button_pressed"]
[connection signal="toggled" from="HBoxContainer/VBoxContainer3/StatusIndicatorVisible" to="." method="_on_status_indicator_visible_toggled"]
[connection signal="dir_selected" from="FileDialog" to="." method="_on_file_dialog_dir_selected"]
[connection signal="file_selected" from="FileDialog" to="." method="_on_file_dialog_file_selected"]
[connection signal="files_selected" from="FileDialog" to="." method="_on_file_dialog_files_selected"]
[connection signal="canceled" from="AcceptDialog" to="." method="_on_accept_dialog_canceled"]
[connection signal="confirmed" from="AcceptDialog" to="." method="_on_accept_dialog_confirmed"]
[connection signal="custom_action" from="AcceptDialog" to="." method="_on_accept_dialog_custom_action"]
[connection signal="canceled" from="ConfirmationDialog" to="." method="_on_confirmation_dialog_canceled"]
[connection signal="confirmed" from="ConfirmationDialog" to="." method="_on_confirmation_dialog_confirmed"]
[connection signal="option_pressed" from="PopupMenu" to="." method="_on_popup_menu_option_pressed"]

View File

@@ -0,0 +1,9 @@
extends Popup
func _ready() -> void:
mouse_exited.connect(_on_mouse_exited)
func _on_mouse_exited():
hide()

View File

@@ -0,0 +1 @@
uid://vyfoelflu5ca

View File

@@ -0,0 +1,14 @@
[gd_scene load_steps=3 format=3 uid="uid://p7lgllpnc8h8"]
[ext_resource type="Script" path="res://scenes/popup/hide_on_mouse_exit.gd" id="1_8lp3w"]
[ext_resource type="Texture2D" uid="uid://cehd300ehf1vw" path="res://icon.webp" id="2_yl4m2"]
[node name="Popup" type="Popup"]
size = Vector2i(128, 128)
visible = true
script = ExtResource("1_8lp3w")
[node name="TextureRect" type="TextureRect" parent="."]
offset_right = 40.0
offset_bottom = 40.0
texture = ExtResource("2_yl4m2")

View File

@@ -0,0 +1,34 @@
extends PopupMenu
signal option_pressed(option: String)
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
add_item("Normal Item")
add_multistate_item("Multistate Item", 3, 0)
add_radio_check_item("Radio Check Item 1")
add_radio_check_item("Radio Check Item 2")
add_check_item("Check Item")
add_separator("Separator")
add_submenu_item("Submenu", "SubPopupMenu")
var submenu: PopupMenu = $SubPopupMenu
submenu.transparent = true
submenu.add_item("Submenu Item 1")
submenu.add_item("Submenu Item 2")
submenu.index_pressed.connect(func(index): option_pressed.emit(submenu.get_item_text(index)))
index_pressed.connect(_on_index_pressed)
func _on_index_pressed(index: int) -> void:
if is_item_checkable(index):
set_item_checked(index, not is_item_checked(index))
match index:
2:
set_item_checked(3, false)
3:
set_item_checked(2, false)
option_pressed.emit(get_item_text(index))

View File

@@ -0,0 +1 @@
uid://dmqie5oywulfi

View File

@@ -0,0 +1,14 @@
[gd_scene load_steps=2 format=3 uid="uid://j7j6fe7plvmt"]
[ext_resource type="Script" path="res://scenes/popup_menu/popup_menu.gd" id="1_hi4jw"]
[node name="PopupMenu" type="PopupMenu"]
transparent_bg = true
visible = true
transparent = true
unfocusable = true
script = ExtResource("1_hi4jw")
[node name="SubPopupMenu" type="PopupMenu" parent="."]
transparent_bg = true
transparent = true

View File

@@ -0,0 +1,26 @@
[gd_scene load_steps=2 format=3 uid="uid://dj15to28g17lb"]
[sub_resource type="GDScript" id="GDScript_aqitk"]
script/source = "extends ProgressBar
func _on_h_slider_value_changed(_value: float) -> void:
value = _value
"
[node name="PopupPanel" type="PopupPanel"]
visible = true
[node name="VBoxContainer" type="VBoxContainer" parent="."]
offset_left = 4.0
offset_top = 4.0
offset_right = 96.0
offset_bottom = 96.0
[node name="ProgressBar" type="ProgressBar" parent="VBoxContainer"]
layout_mode = 2
script = SubResource("GDScript_aqitk")
[node name="HSlider" type="HSlider" parent="VBoxContainer"]
layout_mode = 2
[connection signal="value_changed" from="VBoxContainer/HSlider" to="VBoxContainer/ProgressBar" method="_on_h_slider_value_changed"]

View File

@@ -0,0 +1,27 @@
extends StatusIndicator
@onready var popup_menu: PopupMenu = get_node(menu)
func _ready() -> void:
popup_menu.prefer_native_menu = true
popup_menu.add_item("Quit")
popup_menu.index_pressed.connect(_on_popup_menu_index_pressed)
pressed.connect(_on_pressed)
# Isn't being called on right mouse button because menu is set.
func _on_pressed(mouse_button: int, _mouse_position: Vector2i) -> void:
if mouse_button == MOUSE_BUTTON_LEFT:
var window: Window = get_window()
if window.mode == Window.Mode.MODE_MINIMIZED:
window.mode = Window.Mode.MODE_WINDOWED
window.grab_focus()
func _on_popup_menu_index_pressed(index: int) -> void:
match index:
0:
get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
get_tree().quit()

View File

@@ -0,0 +1 @@
uid://b3ccfgjmssfm3

View File

@@ -0,0 +1,12 @@
[gd_scene load_steps=3 format=3 uid="uid://bfsfek8h27vha"]
[ext_resource type="Texture2D" uid="uid://cehd300ehf1vw" path="res://icon.webp" id="1_ryu0x"]
[ext_resource type="Script" path="res://scenes/status_indicator/status_indicator.gd" id="2_oe45l"]
[node name="StatusIndicator" type="StatusIndicator"]
icon = ExtResource("1_ryu0x")
menu = NodePath("PopupMenu")
script = ExtResource("2_oe45l")
[node name="PopupMenu" type="PopupMenu" parent="."]
prefer_native_menu = true

View File

@@ -0,0 +1,10 @@
extends LineEdit
@export var submit_button: Button
func _ready() -> void:
text_submitted.connect(func(_s): clear(), ConnectFlags.CONNECT_DEFERRED)
if submit_button:
submit_button.pressed.connect(func(): text_submitted.emit(text))

View File

@@ -0,0 +1 @@
uid://evvrji8vwf5l

View File

@@ -0,0 +1,10 @@
extends RichTextLabel
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
meta_clicked.connect(_on_meta_clicked)
func _on_meta_clicked(meta: Variant) -> void:
OS.shell_open(str(meta))

View File

@@ -0,0 +1 @@
uid://bkauiff2v11ga

View File

@@ -0,0 +1,11 @@
extends Window
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
close_requested.connect(_on_close_requested)
func _on_close_requested() -> void:
print("%s %s was hidden." % [str(self.get_class()), name])
hide()

View File

@@ -0,0 +1 @@
uid://op5na21b0cg3

View File

@@ -0,0 +1,30 @@
[gd_scene load_steps=3 format=3 uid="uid://blbehgenpldb"]
[ext_resource type="Script" path="res://scenes/window/url_opener.gd" id="1_cqmq3"]
[ext_resource type="Script" path="res://scenes/window/window.gd" id="1_yx1y1"]
[node name="Window" type="Window"]
initial_position = 2
size = Vector2i(500, 150)
script = ExtResource("1_yx1y1")
[node name="Control" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="RichTextLabel" type="RichTextLabel" parent="Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
bbcode_enabled = true
text = "[url=https://docs.godotengine.org/en/stable/classes/class_window.html]Window, Godot Docs[/url]:
At runtime, [b]Windows[/b] will not close automatically when requested. You need to handle it manually using the [url=https://docs.godotengine.org/en/stable/classes/class_window.html#class-window-signal-close-requested]close_requested[/url] signal (this applies both to pressing the close button and clicking outside of a popup)."
script = ExtResource("1_cqmq3")

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB