Files
room_glitch/ui/room_layout_item.gd

473 lines
5.7 KiB
GDScript

@tool
class_name RoomLayoutItem
extends PanelContainer
signal selected(
item_id: StringName
)
signal moved(
item_id: StringName,
old_position: Vector2,
new_position: Vector2
)
signal moving(
item_id: StringName,
new_position: Vector2
)
var item_id: StringName = &""
var is_dragging: bool = false
var drag_offset: Vector2 = Vector2.ZERO
var drag_start_position: Vector2 = Vector2.ZERO
var base_title: String = ""
var base_subtitle: String = ""
var is_selected: bool = false
var is_active: bool = false
var is_cabinet: bool = false
var is_device: bool = false
var editor_texture: Texture2D = null
var editor_texture_scale: float = 1.0
var footprint_size_pixels: Vector2 = Vector2(
80.0,
75.0
)
@onready var title_label: Label = (
$Margin/VBox/TitleLabel
)
@onready var subtitle_label: Label = (
$Margin/VBox/SubtitleLabel
)
func get_physical_center_offset() -> Vector2:
if (
is_cabinet
or is_device
):
return (
footprint_size_pixels * 0.5
)
return (
size * 0.5
)
func configure(
new_item_id: StringName,
title: String,
subtitle: String
) -> void:
item_id = new_item_id
base_title = title
base_subtitle = subtitle
title_label.text = title
subtitle_label.text = subtitle
func configure_editor_texture(
texture: Texture2D,
texture_scale: float = 1.0
) -> void:
editor_texture = texture
editor_texture_scale = clampf(
texture_scale,
0.1,
1.0
)
queue_redraw()
func _draw_editor_texture(
physical_rect: Rect2
) -> void:
if editor_texture == null:
return
var texture_size := (
editor_texture.get_size()
)
if (
texture_size.x <= 0.0
or texture_size.y <= 0.0
):
return
var available_size := (
physical_rect.size
)
if (
available_size.x <= 0.0
or available_size.y <= 0.0
):
return
#
# Fit the image inside the physical footprint
# while preserving its original aspect ratio.
#
var fit_scale := minf(
available_size.x
/ texture_size.x,
available_size.y
/ texture_size.y
)
fit_scale *= (
editor_texture_scale
)
var draw_size := (
texture_size
* fit_scale
)
var draw_position := (
physical_rect.position
+ (
physical_rect.size
- draw_size
) * 0.5
)
var texture_rect := Rect2(
draw_position,
draw_size
)
draw_texture_rect(
editor_texture,
texture_rect,
false
)
func _draw() -> void:
if is_cabinet:
var rect := Rect2(
Vector2.ZERO,
footprint_size_pixels
)
#
# Cabinet footprint background.
#
draw_rect(
rect,
Color(
0.25,
0.55,
0.95,
0.18
),
true
)
#
# Optional cabinet artwork.
#
_draw_editor_texture(
rect
)
#
# Cabinet footprint outline.
#
draw_rect(
rect,
Color(
0.45,
0.75,
1.0,
1.0
),
false,
3.0
)
#
# Front/player-facing edge.
#
var front_y := (
footprint_size_pixels.y
)
draw_line(
Vector2(
0.0,
front_y
),
Vector2(
footprint_size_pixels.x,
front_y
),
Color(
1.0,
0.85,
0.2,
1.0
),
6.0
)
#
# Center marker on front edge.
#
var center_x := (
footprint_size_pixels.x
* 0.5
)
draw_line(
Vector2(
center_x,
front_y
),
Vector2(
center_x,
front_y - 14.0
),
Color(
1.0,
0.85,
0.2,
1.0
),
4.0
)
return
if is_device:
var rect := Rect2(
Vector2.ZERO,
footprint_size_pixels
)
var fill_color := Color(
0.25,
0.75,
0.45,
0.18
)
var outline_color := Color(
0.4,
0.9,
0.6,
1.0
)
if is_active:
fill_color = Color(
1.0,
0.8,
0.2,
0.18
)
outline_color = Color(
1.0,
0.85,
0.25,
1.0
)
#
# Physical footprint background.
#
draw_rect(
rect,
fill_color,
true
)
#
# Optional device artwork.
#
_draw_editor_texture(
rect
)
#
# Physical footprint outline.
#
draw_rect(
rect,
outline_color,
false,
3.0
)
func set_selected(
value: bool
) -> void:
is_selected = value
if is_selected:
title_label.text = (
"▶ " + base_title
)
else:
title_label.text = base_title
func set_active(
active: bool
) -> void:
is_active = active
if active:
subtitle_label.text = (
"● ACTIVE"
)
else:
subtitle_label.text = (
base_subtitle
)
queue_redraw()
func _gui_input(
event: InputEvent
) -> void:
if event is InputEventMouseButton:
if (
event.button_index
== MOUSE_BUTTON_LEFT
):
if event.pressed:
selected.emit(
item_id
)
is_dragging = true
drag_start_position = (
position
)
drag_offset = (
get_local_mouse_position()
)
else:
if is_dragging:
is_dragging = false
moved.emit(
item_id,
drag_start_position,
position
)
elif event is InputEventMouseMotion:
if is_dragging:
position += (
event.relative
)
moving.emit(
item_id,
position
)
func configure_cabinet_footprint(
width_pixels: float,
depth_pixels: float
) -> void:
is_cabinet = true
footprint_size_pixels = Vector2(
maxf(width_pixels, 10.0),
maxf(depth_pixels, 10.0)
)
custom_minimum_size = (
footprint_size_pixels
)
size = (
footprint_size_pixels
)
pivot_offset = (
get_physical_center_offset()
)
queue_redraw()
func configure_device_footprint(
width_pixels: float,
height_pixels: float
) -> void:
is_device = true
is_cabinet = false
footprint_size_pixels = Vector2(
maxf(
width_pixels,
6.0
),
maxf(
height_pixels,
6.0
)
)
custom_minimum_size = (
footprint_size_pixels
)
size = (
footprint_size_pixels
)
pivot_offset = (
get_physical_center_offset()
)
print(
"[DEVICE FOOTPRINT] ",
item_id,
" pixels=",
footprint_size_pixels,
" size=",
size
)
queue_redraw()