Use static typing in all demos (#1063)

This leads to code that is easier to understand and runs
faster thanks to GDScript's typed instructions.

The untyped declaration warning is now enabled on all projects
where type hints were added. All projects currently run without
any untyped declration warnings.

Dodge the Creeps and Squash the Creeps demos intentionally don't
use type hints to match the documentation, where type hints haven't
been adopted yet (given its beginner focus).
This commit is contained in:
Hugo Locurcio
2024-06-01 12:12:18 +02:00
committed by GitHub
parent 8e9c180278
commit bac1e69164
498 changed files with 5218 additions and 4776 deletions

View File

@@ -1,9 +1,23 @@
extends Node3D
func _ready():
## Camera idle scale effect intensity.
const CAMERA_IDLE_SCALE = 0.005
var counter := 0.0
@onready var camera_base_rotation: Vector3 = $Camera3D.rotation
func _ready() -> void:
# Clear the viewport.
var viewport = $SubViewport
$SubViewport.set_clear_mode(SubViewport.CLEAR_MODE_ONCE)
var viewport: SubViewport = $SubViewport
viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_ONCE
# Retrieve the texture and set it to the viewport quad.
$ViewportQuad.material_override.albedo_texture = viewport.get_texture()
func _process(delta: float) -> void:
# Animate the camera with an "idle" animation.
counter += delta
$Camera3D.rotation.x = camera_base_rotation.y + cos(counter) * CAMERA_IDLE_SCALE
$Camera3D.rotation.y = camera_base_rotation.y + sin(counter) * CAMERA_IDLE_SCALE
$Camera3D.rotation.z = camera_base_rotation.y + sin(counter) * CAMERA_IDLE_SCALE

View File

@@ -66,9 +66,8 @@ tonemap_white = 2.0
script = ExtResource("1_b8rgl")
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.35, 0.6)
fov = 62.0
near = 0.1
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.35, 0.5)
fov = 60.0
[node name="ViewportQuad" type="MeshInstance3D" parent="."]
transform = Transform3D(2, 0, 0, 0, 0, -1.333, 0, 1, 0, 0, 1.2, -4.25)

View File

@@ -1,29 +1,29 @@
extends Node2D
const PAD_SPEED = 150
const INITIAL_BALL_SPEED = 80
const INITIAL_BALL_SPEED = 80.0
var ball_speed = INITIAL_BALL_SPEED
var screen_size = Vector2(640, 400)
var ball_speed := INITIAL_BALL_SPEED
var screen_size := Vector2(640, 400)
# Default ball direction.
var direction = Vector2.LEFT
var pad_size = Vector2(8, 32)
var direction := Vector2.LEFT
var pad_size := Vector2(8, 32)
@onready var ball = $Ball
@onready var left_paddle = $LeftPaddle
@onready var right_paddle = $RightPaddle
@onready var ball: Sprite2D = $Ball
@onready var left_paddle: Sprite2D = $LeftPaddle
@onready var right_paddle: Sprite2D = $RightPaddle
func _ready():
screen_size = get_viewport_rect().size # Get actual size.
func _ready() -> void:
screen_size = get_viewport_rect().size # Get actual size.
pad_size = left_paddle.get_texture().get_size()
func _process(delta):
func _process(delta: float) -> void:
# Get ball position and pad rectangles.
var ball_pos = ball.get_position()
var left_rect = Rect2(left_paddle.get_position() - pad_size * 0.5, pad_size)
var right_rect = Rect2(right_paddle.get_position() - pad_size * 0.5, pad_size)
var ball_pos := ball.get_position()
var left_rect := Rect2(left_paddle.get_position() - pad_size * 0.5, pad_size)
var right_rect := Rect2(right_paddle.get_position() - pad_size * 0.5, pad_size)
# Integrate new ball postion.
ball_pos += direction * ball_speed * delta
@@ -48,7 +48,7 @@ func _process(delta):
ball.set_position(ball_pos)
# Move left pad.
var left_pos = left_paddle.get_position()
var left_pos := left_paddle.get_position()
if left_pos.y > 0 and Input.is_action_pressed(&"left_move_up"):
left_pos.y += -PAD_SPEED * delta
@@ -58,7 +58,7 @@ func _process(delta):
left_paddle.set_position(left_pos)
# Move right pad.
var right_pos = right_paddle.get_position()
var right_pos := right_paddle.get_position()
if right_pos.y > 0 and Input.is_action_pressed(&"right_move_up"):
right_pos.y += -PAD_SPEED * delta
if right_pos.y < screen_size.y and Input.is_action_pressed(&"right_move_down"):

View File

@@ -17,6 +17,10 @@ run/main_scene="res://2d_in_3d.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[input]
left_move_up={

View File

@@ -1,19 +1,18 @@
extends Node2D
var viewport_initial_size = Vector2()
@onready var viewport: SubViewport = $SubViewport
@onready var viewport_initial_size: Vector2i = viewport.size
@onready var viewport_sprite: Sprite2D = $ViewportSprite
@onready var viewport = $SubViewport
@onready var viewport_sprite = $ViewportSprite
func _ready():
func _ready() -> void:
$AnimatedSprite2D.play()
get_viewport().size_changed.connect(_root_viewport_size_changed)
viewport_initial_size = viewport.size
# Called when the root's viewport size changes (i.e. when the window is resized).
# This is done to handle multiple resolutions without losing quality.
func _root_viewport_size_changed():
func _root_viewport_size_changed() -> void:
# The viewport is resized depending on the window height.
# To compensate for the larger resolution, the viewport sprite is scaled down.
viewport.size = Vector2.ONE * get_viewport().size.y

View File

@@ -17,6 +17,10 @@ run/main_scene="res://3d_in_2d.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

View File

@@ -1,7 +1,8 @@
extends Node
## A simple script that rotates the model.
# A simple script to rotate the model.
@onready var model = $Model
@onready var model: Node3D = $Model
func _process(delta):
model.rotate_y(delta * 0.7)
func _process(delta: float) -> void:
model.rotation.y += delta * 0.7

View File

@@ -108,7 +108,7 @@ mesh = SubResource("1")
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(0.877582, 0.229849, -0.420736, 0, 0.877582, 0.479426, 0.479426, -0.420736, 0.770151, -1.68294, 2.25571, 3.0806)
fov = 74.0
fov = 60.0
[node name="OmniLight3D" type="OmniLight3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 2, 1)

View File

@@ -1,28 +1,28 @@
extends Control
## The 3D viewport's shrink factor. For instance, 1 is full resolution,
## 2 is half resolution and 4 is quarter resolution. Lower values look
## sharper but are slower to render.
var scale_factor := 1
# The 3D viewport's shrink factor. For instance, 1 is full resolution,
# 2 is half resolution and 4 is quarter resolution. Lower values look
# sharper but are slower to render.
var scale_factor = 1
var filter_mode = Viewport.SCALING_3D_MODE_BILINEAR
var filter_mode := Viewport.SCALING_3D_MODE_BILINEAR
@onready var viewport = get_tree().root
@onready var scale_label = $VBoxContainer/Scale
@onready var filter_label = $VBoxContainer/Filter
@onready var viewport: Window = get_tree().root
@onready var scale_label: Label = $VBoxContainer/Scale
@onready var filter_label: Label = $VBoxContainer/Filter
func _ready():
viewport.scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR
func _ready() -> void:
viewport.scaling_3d_mode = filter_mode
func _unhandled_input(event):
if event.is_action_pressed("cycle_viewport_resolution"):
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed(&"cycle_viewport_resolution"):
scale_factor = wrapi(scale_factor + 1, 1, 5)
viewport.scaling_3d_scale = 1.0 / scale_factor
scale_label.text = "Scale: %3.0f%%" % (100.0 / scale_factor)
if event.is_action_pressed("toggle_filtering"):
if event.is_action_pressed(&"toggle_filtering"):
filter_mode = wrapi(filter_mode + 1, Viewport.SCALING_3D_MODE_BILINEAR, Viewport.SCALING_3D_MODE_MAX) as Viewport.Scaling3DMode
viewport.scaling_3d_mode = filter_mode
filter_label.text = (

View File

@@ -21,6 +21,10 @@ run/main_scene="res://hud.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

View File

@@ -1,5 +1,4 @@
extends Node3D
# Handle the motion of both player cameras as well as communication with the
# SplitScreen shader to achieve the dynamic split screen effet
#
@@ -19,22 +18,22 @@ extends Node3D
# depending on the distance between players. If false, the thickness will
# be constant and equal to split_line_thickness
@export var max_separation: float = 20.0
@export var split_line_thickness: float = 3.0
@export var split_line_color: Color = Color.BLACK
@export var adaptive_split_line_thickness: bool = true
@export var max_separation := 20.0
@export var split_line_thickness := 3.0
@export var split_line_color := Color.BLACK
@export var adaptive_split_line_thickness := true
@onready var player1 = $"../Player1"
@onready var player2 = $"../Player2"
@onready var view = $View
@onready var viewport1 = $Viewport1
@onready var viewport2 = $Viewport2
@onready var camera1 = viewport1.get_node(^"Camera1")
@onready var camera2 = viewport2.get_node(^"Camera2")
@onready var player1: CharacterBody3D = $"../Player1"
@onready var player2: CharacterBody3D = $"../Player2"
@onready var view: TextureRect = $View
@onready var viewport1: SubViewport = $Viewport1
@onready var viewport2: SubViewport = $Viewport2
@onready var camera1: Camera3D = viewport1.get_node(^"Camera1")
@onready var camera2: Camera3D = viewport2.get_node(^"Camera2")
var viewport_base_height = ProjectSettings.get_setting("display/window/size/viewport_height")
var viewport_base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height"))
func _ready():
func _ready() -> void:
_on_size_changed()
_update_splitscreen()
@@ -44,15 +43,15 @@ func _ready():
view.material.set_shader_parameter("viewport2", viewport2.get_texture())
func _process(_delta):
func _process(_delta: float) -> void:
_move_cameras()
_update_splitscreen()
func _move_cameras():
var position_difference = _compute_position_difference_in_world()
func _move_cameras() -> void:
var position_difference := _get_position_difference_in_world()
var distance = clamp(_compute_horizontal_length(position_difference), 0, max_separation)
var distance := clampf(_get_horizontal_length(position_difference), 0, max_separation)
position_difference = position_difference.normalized() * distance
@@ -63,37 +62,38 @@ func _move_cameras():
camera2.position.z = player2.position.z - position_difference.z / 2.0
func _update_splitscreen():
var screen_size = get_viewport().get_visible_rect().size
var player1_position = camera1.unproject_position(player1.position) / screen_size
var player2_position = camera2.unproject_position(player2.position) / screen_size
func _update_splitscreen() -> void:
var screen_size := get_viewport().get_visible_rect().size
var player1_position := camera1.unproject_position(player1.position) / screen_size
var player2_position := camera2.unproject_position(player2.position) / screen_size
var thickness
var thickness := 0.0
if adaptive_split_line_thickness:
var position_difference = _compute_position_difference_in_world()
var distance = _compute_horizontal_length(position_difference)
var position_difference := _get_position_difference_in_world()
var distance := _get_horizontal_length(position_difference)
thickness = lerpf(0, split_line_thickness, (distance - max_separation) / max_separation)
thickness = clampf(thickness, 0, split_line_thickness)
else:
thickness = split_line_thickness
view.material.set_shader_parameter("split_active", _get_split_state())
view.material.set_shader_parameter("split_active", _is_split_state())
view.material.set_shader_parameter("player1_position", player1_position)
view.material.set_shader_parameter("player2_position", player2_position)
view.material.set_shader_parameter("split_line_thickness", thickness)
view.material.set_shader_parameter("split_line_color", split_line_color)
# Split screen is active if players are too far apart from each other.
# Only the horizontal components (x, z) are used for distance computation
func _get_split_state():
var position_difference = _compute_position_difference_in_world()
var separation_distance = _compute_horizontal_length(position_difference)
## Returns `true` if split screen is active (which occurs when players are
## too far apart from each other), `false` otherwise.
## Only the horizontal components (x, z) are used for distance computation.
func _is_split_state() -> bool:
var position_difference := _get_position_difference_in_world()
var separation_distance := _get_horizontal_length(position_difference)
return separation_distance > max_separation
func _on_size_changed():
var screen_size = get_viewport().get_visible_rect().size
func _on_size_changed() -> void:
var screen_size := get_viewport().get_visible_rect().size
$Viewport1.size = screen_size
$Viewport2.size = screen_size
@@ -101,9 +101,9 @@ func _on_size_changed():
view.material.set_shader_parameter("viewport_size", screen_size)
func _compute_position_difference_in_world():
func _get_position_difference_in_world() -> Vector3:
return player2.position - player1.position
func _compute_horizontal_length(vec):
func _get_horizontal_length(vec: Vector3) -> float:
return Vector2(vec.x, vec.z).length()

View File

@@ -2,16 +2,16 @@ extends CharacterBody3D
# Moves the player
@export_range(1, 2) var player_id: int = 1
@export var walk_speed: float = 2
@export_range(1, 2) var player_id := 1
@export var walk_speed := 2.0
func _physics_process(_delta):
var move_direction = Input.get_vector(
"move_left_player" + str(player_id),
"move_right_player" + str(player_id),
"move_up_player" + str(player_id),
"move_down_player" + str(player_id),
func _physics_process(_delta: float) -> void:
var move_direction := Input.get_vector(
&"move_left_player" + str(player_id),
&"move_right_player" + str(player_id),
&"move_up_player" + str(player_id),
&"move_down_player" + str(player_id),
)
velocity.x += move_direction.x * walk_speed
velocity.z += move_direction.y * walk_speed

View File

@@ -18,6 +18,10 @@ run/main_scene="res://split_screen.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[input]
move_up_player1={
@@ -86,5 +90,4 @@ common/physics_ticks_per_second=120
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"
lights_and_shadows/directional_shadow/soft_shadow_filter_quality=4
environment/defaults/default_clear_color=Color(1, 1, 1, 1)
anti_aliasing/quality/msaa_3d=2

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=63 format=3 uid="uid://dksa68cph6y4b"]
[gd_scene load_steps=67 format=3 uid="uid://dksa68cph6y4b"]
[ext_resource type="Script" path="res://camera_controller.gd" id="2"]
[ext_resource type="Shader" path="res://split_screen.gdshader" id="3"]
@@ -13,14 +13,12 @@ ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
sky_material = SubResource("ProceduralSkyMaterial_16la2")
[sub_resource type="Environment" id="Environment_vdrvu"]
background_mode = 2
sky = SubResource("Sky_i64ko")
ambient_light_source = 2
ambient_light_source = 3
ambient_light_color = Color(0.79, 0.8775, 1, 1)
ambient_light_sky_contribution = 0.0
ambient_light_energy = 0.33
reflected_light_source = 2
tonemap_mode = 2
glow_enabled = true
[sub_resource type="ShaderMaterial" id="1"]
shader = ExtResource("3")
@@ -67,6 +65,24 @@ emission = Color(0.12549, 0.501961, 1, 1)
material = SubResource("6")
size = Vector2(200, 200)
[sub_resource type="Gradient" id="Gradient_3phjx"]
offsets = PackedFloat32Array(0.139344, 0.196721, 0.237705, 0.377049, 0.598361, 0.795082, 1)
colors = PackedColorArray(0.08, 0.432667, 1, 1, 0.945098, 1, 0.929412, 1, 0.574026, 0.479268, 0.220411, 1, 1, 0.7525, 0.45, 1, 0.0322, 0.23, 0.0322, 1, 0.181569, 0.353991, 0.245845, 1, 1, 1, 1, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_2bwlb"]
noise_type = 4
domain_warp_enabled = true
domain_warp_frequency = 0.002
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_ha3y6"]
seamless = true
color_ramp = SubResource("Gradient_3phjx")
noise = SubResource("FastNoiseLite_2bwlb")
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i0wmt"]
albedo_texture = SubResource("NoiseTexture2D_ha3y6")
uv1_scale = Vector3(64, 64, 64)
[sub_resource type="BoxShape3D" id="8"]
[sub_resource type="BoxShape3D" id="9"]
@@ -265,6 +281,17 @@ surface_material_override/0 = SubResource("StandardMaterial3D_63nwq")
[node name="OmniLight3D" type="OmniLight3D" parent="Player1"]
light_color = Color(1, 0, 0, 1)
light_energy = 2.5
omni_range = 10.0
[node name="Label3D" type="Label3D" parent="Player1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
pixel_size = 0.01
offset = Vector2(0, 50)
billboard = 1
double_sided = false
modulate = Color(1, 0.323333, 0.3, 1)
text = "P1"
[node name="Player2" type="CharacterBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.184, 0.875, 3.019)
@@ -286,12 +313,24 @@ surface_material_override/0 = SubResource("StandardMaterial3D_wi7e2")
[node name="OmniLight3D" type="OmniLight3D" parent="Player2"]
light_color = Color(0.12549, 0.501961, 1, 1)
light_energy = 2.5
omni_range = 10.0
[node name="Label3D" type="Label3D" parent="Player2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
pixel_size = 0.01
offset = Vector2(0, 50)
billboard = 1
double_sided = false
modulate = Color(0.3, 0.65, 1, 1)
text = "P2"
[node name="Ground" type="StaticBody3D" parent="."]
[node name="Mesh" type="MeshInstance3D" parent="Ground"]
transform = Transform3D(20, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0)
mesh = SubResource("7")
surface_material_override/0 = SubResource("StandardMaterial3D_i0wmt")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
transform = Transform3D(200, 0, 0, 0, 1, 0, 0, 0, 200, 0, -1, 0)

View File

@@ -1,13 +1,13 @@
@tool
extends Node3D
## Sets a random color to all objects in the "walls" group.
## To use, attach this script to the "Walls" node.
# Set a random color to all objects in the "walls" group.
# To use, attach this script to the "Walls" node.
func _ready():
var walls = get_tree().get_nodes_in_group("walls")
func _ready() -> void:
var walls := get_tree().get_nodes_in_group("walls")
for wall in walls:
var material = StandardMaterial3D.new()
var material := StandardMaterial3D.new()
material.albedo_color = Color(randf(), randf(), randf())
wall.material_override = material

View File

@@ -1,17 +1,19 @@
extends Node3D
# Used for checking if the mouse is inside the Area3D.
var is_mouse_inside = false
# The last processed input touch/mouse event. To calculate relative movement.
var last_event_pos2D = null
# The time of the last event in seconds since engine start.
var last_event_time: float = -1.0
## Used for checking if the mouse is inside the Area3D.
var is_mouse_inside := false
@onready var node_viewport = $SubViewport
@onready var node_quad = $Quad
@onready var node_area = $Quad/Area3D
## The last processed input touch/mouse event. Used to calculate relative movement.
var last_event_pos2D := Vector2()
func _ready():
## The time of the last event in seconds since engine start.
var last_event_time := -1.0
@onready var node_viewport: SubViewport = $SubViewport
@onready var node_quad: MeshInstance3D = $Quad
@onready var node_area: Area3D = $Quad/Area3D
func _ready() -> void:
node_area.mouse_entered.connect(_mouse_entered_area)
node_area.mouse_exited.connect(_mouse_exited_area)
node_area.input_event.connect(_mouse_input_event)
@@ -21,20 +23,20 @@ func _ready():
set_process(false)
func _process(_delta):
func _process(_delta: float) -> void:
# NOTE: Remove this function if you don't plan on using billboard settings.
rotate_area_to_billboard()
func _mouse_entered_area():
func _mouse_entered_area() -> void:
is_mouse_inside = true
func _mouse_exited_area():
func _mouse_exited_area() -> void:
is_mouse_inside = false
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
# Check if the event is a non-mouse/non-touch event
for mouse_event in [InputEventMouseButton, InputEventMouseMotion, InputEventScreenDrag, InputEventScreenTouch]:
if is_instance_of(event, mouse_event):
@@ -44,23 +46,23 @@ func _unhandled_input(event):
node_viewport.push_input(event)
func _mouse_input_event(_camera: Camera3D, event: InputEvent, event_position: Vector3, _normal: Vector3, _shape_idx: int):
# Get mesh size to detect edges and make conversions. This code only support PlaneMesh and QuadMesh.
var quad_mesh_size = node_quad.mesh.size
func _mouse_input_event(_camera: Camera3D, event: InputEvent, event_position: Vector3, _normal: Vector3, _shape_idx: int) -> void:
# Get mesh size to detect edges and make conversions. This code only supports PlaneMesh and QuadMesh.
var quad_mesh_size: Vector2 = node_quad.mesh.size
# Event position in Area3D in world coordinate space.
var event_pos3D = event_position
var event_pos3D := event_position
# Current time in seconds since engine start.
var now: float = Time.get_ticks_msec() / 1000.0
var now := Time.get_ticks_msec() / 1000.0
# Convert position to a coordinate space relative to the Area3D node.
# NOTE: affine_inverse accounts for the Area3D node's scale, rotation, and position in the scene!
# NOTE: `affine_inverse()` accounts for the Area3D node's scale, rotation, and position in the scene!
event_pos3D = node_quad.global_transform.affine_inverse() * event_pos3D
# TODO: Adapt to bilboard mode or avoid completely.
var event_pos2D: Vector2 = Vector2()
var event_pos2D := Vector2()
if is_mouse_inside:
# Convert the relative event position from 3D to 2D.
@@ -109,15 +111,15 @@ func _mouse_input_event(_camera: Camera3D, event: InputEvent, event_position: Ve
node_viewport.push_input(event)
func rotate_area_to_billboard():
var billboard_mode = node_quad.get_surface_override_material(0).billboard_mode
func rotate_area_to_billboard() -> void:
var billboard_mode: BaseMaterial3D.BillboardMode = node_quad.get_surface_override_material(0).billboard_mode
# Try to match the area with the material's billboard setting, if enabled.
if billboard_mode > 0:
# Get the camera.
var camera = get_viewport().get_camera_3d()
var camera := get_viewport().get_camera_3d()
# Look in the same direction as the camera.
var look = camera.to_global(Vector3(0, 0, -100)) - camera.global_transform.origin
var look := camera.to_global(Vector3(0, 0, -100)) - camera.global_transform.origin
look = node_area.position + look
# Y-Billboard: Lock Y rotation, but gives bad results if the camera is tilted.

View File

@@ -18,6 +18,10 @@ run/main_scene="res://gui_in_3d.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[gui]
theme/default_theme_scale=2.0

View File

@@ -17,6 +17,10 @@ run/main_scene="res://screen_capture.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

View File

@@ -1,13 +1,23 @@
extends Node
@onready var captured_image = $CapturedImage
@onready var captured_image: TextureRect = $CapturedImage
@onready var capture_button: Button = $CaptureButton
func _on_CaptureButton_pressed():
func _ready() -> void:
# Focus button for keyboard/gamepad-friendly navigation.
capture_button.grab_focus()
func _on_capture_button_pressed() -> void:
# Retrieve the captured image.
var img = get_viewport().get_texture().get_image()
var img := get_viewport().get_texture().get_image()
# Create a texture for it.
var tex = ImageTexture.create_from_image(img)
var tex := ImageTexture.create_from_image(img)
# Set the texture to the captured image node.
captured_image.set_texture(tex)
# Colorize the button with a random color, so you can see which button belongs to which capture.
capture_button.modulate = Color.from_hsv(randf(), randf_range(0.2, 0.8), 1.0)

View File

@@ -41,6 +41,7 @@ offset_left = 50.0
offset_top = 50.0
offset_right = 190.0
offset_bottom = 110.0
text = "Capture screen"
text = "Capture
Screen"
[connection signal="pressed" from="CaptureButton" to="." method="_on_CaptureButton_pressed"]
[connection signal="pressed" from="CaptureButton" to="." method="_on_capture_button_pressed"]