473 lines
5.7 KiB
GDScript
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()
|