114 lines
4.1 KiB
GDScript
114 lines
4.1 KiB
GDScript
extends Panel
|
|
## One inventory slot: icon, stack count, optional hotbar number. Renders a
|
|
## stack and reports clicks; it never changes the inventory itself.
|
|
|
|
signal clicked(index: int, right: bool, shift: bool)
|
|
|
|
const UITheme = preload("res://scripts/ui/theme.gd")
|
|
|
|
var index := 0
|
|
var _icon: TextureRect
|
|
var _count: Label
|
|
var _key: Label
|
|
var _style: StyleBoxFlat
|
|
var _selected_style: StyleBoxFlat
|
|
var _stack = null
|
|
var _wear: ColorRect
|
|
var _wear_fill: ColorRect
|
|
|
|
func _init(i: int = 0, size_px: int = 64, key_label: String = "") -> void:
|
|
index = i
|
|
custom_minimum_size = Vector2(size_px, size_px)
|
|
mouse_filter = Control.MOUSE_FILTER_STOP
|
|
_style = UITheme.box(UITheme.SLOT_BG, UITheme.SLOT_BORDER, 2, 5, 0)
|
|
_selected_style = UITheme.box(UITheme.SLOT_BG.lightened(0.15), UITheme.SELECTED, 3, 5, 0)
|
|
add_theme_stylebox_override("panel", _style)
|
|
|
|
_icon = TextureRect.new()
|
|
_icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
|
_icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
|
_icon.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
_icon.offset_left = 5; _icon.offset_top = 5; _icon.offset_right = -5; _icon.offset_bottom = -5
|
|
_icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(_icon)
|
|
|
|
_count = UITheme.label("", 15)
|
|
_count.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_RIGHT)
|
|
_count.grow_horizontal = Control.GROW_DIRECTION_BEGIN
|
|
_count.grow_vertical = Control.GROW_DIRECTION_BEGIN
|
|
_count.offset_right = -5
|
|
_count.offset_bottom = -2
|
|
_count.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(_count)
|
|
|
|
_key = UITheme.label(key_label, 12, UITheme.TEXT_DIM)
|
|
_key.position = Vector2(5, 2)
|
|
_key.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(_key)
|
|
|
|
_wear = ColorRect.new()
|
|
_wear.color = Color(0, 0, 0, 0.6)
|
|
_wear.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_WIDE)
|
|
_wear.offset_left = 6
|
|
_wear.offset_right = -6
|
|
_wear.offset_top = -9
|
|
_wear.offset_bottom = -5
|
|
_wear.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
_wear.visible = false
|
|
add_child(_wear)
|
|
_wear_fill = ColorRect.new()
|
|
_wear_fill.anchor_bottom = 1.0
|
|
_wear_fill.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
_wear.add_child(_wear_fill)
|
|
|
|
func set_stack(stack) -> void:
|
|
_stack = stack
|
|
if stack == null:
|
|
_icon.texture = null
|
|
_count.text = ""
|
|
tooltip_text = ""
|
|
_wear.visible = false
|
|
return
|
|
_icon.texture = ItemDB.icon(stack.id)
|
|
_count.text = str(stack.count) if stack.count > 1 else ""
|
|
var def := ItemDB.get_item(stack.id)
|
|
tooltip_text = "%s\n%s" % [def.get("name", stack.id), def.get("description", "")]
|
|
# Wear: a bar along the bottom once a tool or weapon has been used.
|
|
var full := ItemDB.max_durability(stack.id)
|
|
var left := ItemDB.durability(stack)
|
|
if full > 0 and left < full:
|
|
var k := float(left) / full
|
|
_wear.visible = true
|
|
_wear_fill.anchor_right = k
|
|
_wear_fill.color = Color(0.85, 0.25, 0.2) if k < 0.2 else (Color(0.9, 0.75, 0.25) if k < 0.5 else Color(0.45, 0.8, 0.35))
|
|
tooltip_text += "\n%d of %d uses left" % [left, full]
|
|
elif stack.has("rot") and Inventory.keeps_for(String(stack.id)) > 0.0:
|
|
# Food: a bar that runs down green to brown as it goes off.
|
|
var k := Inventory.freshness(stack)
|
|
_wear.visible = true
|
|
_wear_fill.anchor_right = maxf(k, 0.04)
|
|
_wear_fill.color = Color(0.45, 0.8, 0.35).lerp(Color(0.5, 0.33, 0.15), 1.0 - k)
|
|
tooltip_text += "\n" + freshness_text(stack)
|
|
else:
|
|
_wear.visible = false
|
|
|
|
## "Fresh", "Going off (about 9 hours left)", "Nearly rotten (2 hours left)".
|
|
static func freshness_text(stack) -> String:
|
|
var k := Inventory.freshness(stack)
|
|
var h := Inventory.hours_left(stack)
|
|
var left := ("%d hours left" % roundi(h)) if h < 48.0 else ("%d days left" % roundi(h / 24.0))
|
|
if k > 0.6:
|
|
return "Fresh (%s)" % left
|
|
if k > 0.2:
|
|
return "Going off (%s)" % left
|
|
return "Nearly rotten (%s)" % left
|
|
|
|
func set_selected(on: bool) -> void:
|
|
add_theme_stylebox_override("panel", _selected_style if on else _style)
|
|
|
|
func _gui_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseButton and event.pressed:
|
|
if event.button_index == MOUSE_BUTTON_LEFT or event.button_index == MOUSE_BUTTON_RIGHT:
|
|
clicked.emit(index, event.button_index == MOUSE_BUTTON_RIGHT, event.shift_pressed)
|
|
accept_event()
|