diff --git a/godot/.editorconfig b/godot/.editorconfig index f28239b..1b6931b 100644 --- a/godot/.editorconfig +++ b/godot/.editorconfig @@ -2,3 +2,11 @@ root = true [*] charset = utf-8 + +[*.gd] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + diff --git a/godot/addons/collections/int_range.gd b/godot/addons/collections/int_range.gd index 462aeb0..abad5b0 100644 --- a/godot/addons/collections/int_range.gd +++ b/godot/addons/collections/int_range.gd @@ -19,7 +19,7 @@ func _init(start: int, end: int, inclusive: bool = false) -> void: self.inclusive = inclusive static func from_sized(value: Variant) -> Result: - match KCUtils.get_size(value): + match K.get_size(value): var len when len.is_ok(): return Result.ok(IntRange.new(0, len.unwrap())) var e: return e diff --git a/godot/addons/utils/utils.gd b/godot/addons/utils/utils.gd index 5bf8c56..596834b 100644 --- a/godot/addons/utils/utils.gd +++ b/godot/addons/utils/utils.gd @@ -1,4 +1,4 @@ -class_name KCUtils +class_name K static func remove_children(node: Node, delete: bool = true): for i in range(node.get_child_count() - 1, -1, -1): @@ -15,6 +15,10 @@ static func get_class_name(value: Object) -> String: _: return script.get_instance_base_type() _: return value.get_class() +static func is_array_like(value: Variant) -> bool: + var type = typeof(value) + return type >= 28 and type <= 38 or type == TYPE_STRING or type == TYPE_STRING_NAME + static func is_string_like(value: Variant) -> bool: match typeof(value): TYPE_STRING: return true @@ -79,3 +83,9 @@ static func get_size(value: Variant) -> Result: static func len(value: Variant) -> int: return get_size(value).unwrap() + +static func iter(value: Variant) -> Iterator: + if is_array_like(value): return ListIterator.from_array(value) + if typeof(value) == TYPE_OBJECT: return VariantIterator.new(value) + if typeof(value) == TYPE_DICTIONARY: return DictionaryIterator.new(value) + return SingletonIterator.new(value) diff --git a/godot/assets/icons/10mm_icon.tres b/godot/assets/icons/10mm_icon.tres new file mode 100644 index 0000000..bd003d1 --- /dev/null +++ b/godot/assets/icons/10mm_icon.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://csnm0disev20f"] + +[ext_resource type="Texture2D" uid="uid://d3ergv453flsw" path="res://assets/sprites.png" id="1_nybgi"] + +[resource] +atlas = ExtResource("1_nybgi") +region = Rect2(72, 272, 48, 32) diff --git a/godot/assets/icons/key_icon.tres b/godot/assets/icons/key_icon.tres index 5ed140d..ce5ab5d 100644 --- a/godot/assets/icons/key_icon.tres +++ b/godot/assets/icons/key_icon.tres @@ -4,5 +4,4 @@ [resource] atlas = ExtResource("1_gm5ao") -region = Rect2(256, 128, 64, 64) -margin = Rect2(-10, -12, -20, -20) +region = Rect2(275, 142, 25, 39) diff --git a/godot/assets/icons/pistol_icon.tres b/godot/assets/icons/pistol_icon.tres index 2c293e7..95eb8b1 100644 --- a/godot/assets/icons/pistol_icon.tres +++ b/godot/assets/icons/pistol_icon.tres @@ -4,5 +4,4 @@ [resource] atlas = ExtResource("1_y5otb") -region = Rect2(192, 256, 64, 64) -margin = Rect2(0, -10, 0, -12) +region = Rect2(193, 272, 62, 40) diff --git a/godot/resources/items/9mm_ammo.tres b/godot/resources/items/9mm_ammo.tres new file mode 100644 index 0000000..d631e3b --- /dev/null +++ b/godot/resources/items/9mm_ammo.tres @@ -0,0 +1,12 @@ +[gd_resource type="Resource" script_class="Item" load_steps=3 format=3 uid="uid://ud2qc6eul8lt"] + +[ext_resource type="Script" uid="uid://d1imxjix6ljul" path="res://src/attributes/attribute.gd" id="1_gkq1r"] +[ext_resource type="Script" uid="uid://bqprls343ue6e" path="res://src/items/item.gd" id="2_4ckx0"] + +[resource] +script = ExtResource("2_4ckx0") +name = "9mm Ammo" +description = "" +max_stack = 99 +attributes = Array[ExtResource("1_gkq1r")]([]) +metadata/_custom_type_script = "uid://bqprls343ue6e" diff --git a/godot/resources/items/key.tres b/godot/resources/items/key.tres index 2928796..6b097db 100644 --- a/godot/resources/items/key.tres +++ b/godot/resources/items/key.tres @@ -1,12 +1,14 @@ -[gd_resource type="Resource" script_class="Item" load_steps=3 format=3 uid="uid://cqfnwpmo4fyv4"] +[gd_resource type="Resource" script_class="Item" load_steps=4 format=3 uid="uid://cqfnwpmo4fyv4"] -[ext_resource type="Script" uid="uid://bqprls343ue6e" path="res://src/item.gd" id="1_7ur50"] +[ext_resource type="Script" uid="uid://d1imxjix6ljul" path="res://src/attributes/attribute.gd" id="1_nv3up"] [ext_resource type="Texture2D" uid="uid://dngw0c0dc6u7x" path="res://assets/icons/key_icon.tres" id="1_ykwyx"] +[ext_resource type="Script" uid="uid://bqprls343ue6e" path="res://src/items/item.gd" id="3_4rdgs"] [resource] -script = ExtResource("1_7ur50") +script = ExtResource("3_4rdgs") name = "Debug Key" description = "An unusual key card." max_stack = 1 icon = ExtResource("1_ykwyx") +attributes = Array[ExtResource("1_nv3up")]([]) metadata/_custom_type_script = "uid://bqprls343ue6e" diff --git a/godot/resources/items/pistol.tres b/godot/resources/items/pistol.tres index f471afa..5b4b289 100644 --- a/godot/resources/items/pistol.tres +++ b/godot/resources/items/pistol.tres @@ -1,16 +1,32 @@ -[gd_resource type="Resource" script_class="EquippableItem" load_steps=5 format=3 uid="uid://crgwey6ibaf2h"] +[gd_resource type="Resource" script_class="EquippableItem" load_steps=10 format=3 uid="uid://crgwey6ibaf2h"] [ext_resource type="PackedScene" uid="uid://isqkayrtr7t8" path="res://scenes/pistol.tscn" id="1_6ttue"] +[ext_resource type="Script" uid="uid://d1imxjix6ljul" path="res://src/attributes/attribute.gd" id="1_7dru5"] [ext_resource type="Texture2D" uid="uid://dvxrifa0iu8ql" path="res://assets/icons/pistol_icon.tres" id="1_112eb"] [ext_resource type="PackedScene" uid="uid://dfljhd4e3l6j2" path="res://scenes/pistol_preview.tscn" id="1_gintf"] -[ext_resource type="Script" uid="uid://c710qg683rqbc" path="res://src/equippable_item.gd" id="1_lqglu"] +[ext_resource type="Script" uid="uid://c710qg683rqbc" path="res://src/items/equippable_item.gd" id="1_lqglu"] +[ext_resource type="Script" uid="uid://bbigpwchxitb5" path="res://src/attributes/ammo_attribute.gd" id="2_j7ges"] +[ext_resource type="Script" uid="uid://c1y3loxtmkeg3" path="res://src/attributes/equippable_attribute.gd" id="3_fcfbw"] + +[sub_resource type="Resource" id="Resource_6opap"] +script = ExtResource("2_j7ges") +max_capacity = 10 +metadata/_custom_type_script = "uid://bbigpwchxitb5" + +[sub_resource type="Resource" id="Resource_moakd"] +script = ExtResource("3_fcfbw") +type = 0 +metadata/_custom_type_script = "uid://c1y3loxtmkeg3" [resource] script = ExtResource("1_lqglu") +type = 0 +ammo_capacity = 0 name = "Pistol" description = "A semi-automatic pistol. Fires 10mm ammunition from a 10-round magazine. Easy to use, high rate of fire." max_stack = 1 icon = ExtResource("1_112eb") scene = ExtResource("1_6ttue") preview_scene = ExtResource("1_gintf") +attributes = Array[ExtResource("1_7dru5")]([SubResource("Resource_6opap"), SubResource("Resource_moakd")]) metadata/_custom_type_script = "uid://c710qg683rqbc" diff --git a/godot/resources/player_inventory.tres b/godot/resources/player_inventory.tres index 2fb8b9f..aa6d29b 100644 --- a/godot/resources/player_inventory.tres +++ b/godot/resources/player_inventory.tres @@ -1,7 +1,7 @@ [gd_resource type="Resource" script_class="Inventory" load_steps=5 format=3 uid="uid://bllq6ri54q3ne"] -[ext_resource type="Script" uid="uid://1rjq1ttxq4nd" path="res://src/item_instance.gd" id="1_uptie"] -[ext_resource type="Script" uid="uid://dh4ytedxidq0x" path="res://src/inventory.gd" id="2_1njko"] +[ext_resource type="Script" uid="uid://1rjq1ttxq4nd" path="res://src/items/item_instance.gd" id="1_uptie"] +[ext_resource type="Script" uid="uid://dh4ytedxidq0x" path="res://src/items/inventory.gd" id="2_1njko"] [ext_resource type="Resource" uid="uid://cqfnwpmo4fyv4" path="res://resources/items/key.tres" id="2_85a8j"] [sub_resource type="Resource" id="Resource_hfe8y"] diff --git a/godot/scenes/box_ui.tres b/godot/scenes/box_ui.tres index b95462b..108702a 100644 --- a/godot/scenes/box_ui.tres +++ b/godot/scenes/box_ui.tres @@ -1,23 +1,9 @@ -[gd_resource type="Theme" load_steps=6 format=3 uid="uid://bb6tvyqikcf3r"] +[gd_resource type="Theme" load_steps=3 format=3 uid="uid://bb6tvyqikcf3r"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_odwru"] -bg_color = Color(0.6, 0.6, 0.6, 0) - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_t6lws"] bg_color = Color(0.92549, 0.243137, 0.0392157, 1) -[sub_resource type="SystemFont" id="SystemFont_t6lws"] -font_names = PackedStringArray("Monospace") -font_weight = 600 -keep_rounding_remainders = false -multichannel_signed_distance_field = true - -[sub_resource type="SystemFont" id="SystemFont_odwru"] -font_names = PackedStringArray("monospace") -font_weight = 500 -multichannel_signed_distance_field = true - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_4gq11"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nj55m"] bg_color = Color(0.6, 0.6, 0.6, 0) border_width_left = 1 border_width_top = 1 @@ -26,20 +12,8 @@ border_width_bottom = 1 border_color = Color(0.92549, 0.243137, 0.0392157, 1) [resource] -BoxContent/base_type = &"Panel" -BoxContent/styles/panel = SubResource("StyleBoxFlat_odwru") -BoxHeader/base_type = &"PanelContainer" -BoxHeader/styles/panel = SubResource("StyleBoxFlat_t6lws") -BoxHeaderLabel/base_type = &"Label" -BoxHeaderLabel/colors/font_color = Color(0, 0, 0, 1) -BoxHeaderLabel/font_sizes/font_size = 8 -BoxHeaderLabel/fonts/font = SubResource("SystemFont_t6lws") -HBoxContainer/constants/separation = 8 -Label/font_sizes/font_size = 12 -Label/fonts/font = SubResource("SystemFont_odwru") -MarginContainer/constants/margin_bottom = 4 -MarginContainer/constants/margin_left = 4 -MarginContainer/constants/margin_right = 4 -MarginContainer/constants/margin_top = 4 -PanelContainer/styles/panel = SubResource("StyleBoxFlat_4gq11") -RichTextLabel/colors/default_color = Color(0.0745098, 0.0745098, 0.0745098, 1) +BoxTitle/base_type = &"PanelContainer" +BoxTitle/styles/panel = SubResource("StyleBoxFlat_odwru") +BoxTitleText/base_type = &"Label" +BoxTitleText/colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) +PanelContainer/styles/panel = SubResource("StyleBoxFlat_nj55m") diff --git a/godot/scenes/box_ui.tscn b/godot/scenes/box_ui.tscn index 32ecc42..8b534c1 100644 --- a/godot/scenes/box_ui.tscn +++ b/godot/scenes/box_ui.tscn @@ -1,27 +1,35 @@ -[gd_scene load_steps=2 format=3 uid="uid://cidwsnulug6fl"] +[gd_scene load_steps=3 format=3 uid="uid://cidwsnulug6fl"] [ext_resource type="Theme" uid="uid://bb6tvyqikcf3r" path="res://scenes/box_ui.tres" id="1_e1aew"] +[ext_resource type="Script" uid="uid://bnumwlio6adb8" path="res://src/ui/box.gd" id="2_jp73w"] -[node name="Box" type="PanelContainer"] +[node name="Box" type="PanelContainer" node_paths=PackedStringArray("title_label", "body_container")] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 theme = ExtResource("1_e1aew") +script = ExtResource("2_jp73w") +title_label = NodePath("Container/Header/TitleContainer/Label") +body_container = NodePath("Container/Content") -[node name="VBoxContainer" type="VBoxContainer" parent="."] +[node name="Container" type="VBoxContainer" parent="."] layout_mode = 2 -[node name="Header" type="PanelContainer" parent="VBoxContainer"] +[node name="Header" type="PanelContainer" parent="Container"] layout_mode = 2 theme = ExtResource("1_e1aew") -theme_type_variation = &"BoxHeader" +theme_type_variation = &"BoxTitle" -[node name="TitleContainer" type="MarginContainer" parent="VBoxContainer/Header"] +[node name="TitleContainer" type="MarginContainer" parent="Container/Header"] layout_mode = 2 -[node name="Body" type="PanelContainer" parent="VBoxContainer"] +[node name="Label" type="Label" parent="Container/Header/TitleContainer"] +layout_mode = 2 +theme_type_variation = &"BoxTitleText" + +[node name="Content" type="PanelContainer" parent="Container"] layout_mode = 2 size_flags_vertical = 3 theme = ExtResource("1_e1aew") diff --git a/godot/scenes/context_menu.tscn b/godot/scenes/context_menu.tscn new file mode 100644 index 0000000..2bf8bbf --- /dev/null +++ b/godot/scenes/context_menu.tscn @@ -0,0 +1,9 @@ +[gd_scene format=3 uid="uid://bgn32l1f007w2"] + +[node name="ContextMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/godot/scenes/inventory.tscn b/godot/scenes/inventory.tscn index fa24b3b..8139829 100644 --- a/godot/scenes/inventory.tscn +++ b/godot/scenes/inventory.tscn @@ -1,15 +1,13 @@ -[gd_scene load_steps=14 format=3 uid="uid://cn7tgd4y67wnd"] +[gd_scene load_steps=12 format=3 uid="uid://cn7tgd4y67wnd"] -[ext_resource type="Script" uid="uid://qvoqvonnxwfc" path="res://src/inventory_ui.gd" id="1_a0rpf"] -[ext_resource type="Script" uid="uid://bx4wxlm5mv268" path="res://src/root_control.gd" id="1_as33y"] [ext_resource type="Theme" uid="uid://bb6tvyqikcf3r" path="res://scenes/box_ui.tres" id="1_sr8g6"] [ext_resource type="Resource" uid="uid://bllq6ri54q3ne" path="res://resources/player_inventory.tres" id="2_as33y"] +[ext_resource type="Script" uid="uid://b7j7weoa8tikm" path="res://src/ui/inventory_screen.gd" id="2_g71ie"] [ext_resource type="PackedScene" uid="uid://gn8k2ir47n1m" path="res://scenes/inventory_item.tscn" id="3_tg4gd"] -[ext_resource type="Script" uid="uid://bpwbaanf6w65h" path="res://src/index_carousel.gd" id="5_uae8j"] -[ext_resource type="Script" uid="uid://c8m7eq6a3tpgu" path="res://src/item_details_ui.gd" id="6_s887n"] +[ext_resource type="Script" uid="uid://c8m7eq6a3tpgu" path="res://src/ui/item_detail_ui.gd" id="4_yyk2a"] +[ext_resource type="Script" uid="uid://bpwbaanf6w65h" path="res://src/ui/index_carousel.gd" id="5_uae8j"] [ext_resource type="Resource" uid="uid://cxm3s081hnw8l" path="res://resources/player_equipment.tres" id="7_s887n"] [ext_resource type="PackedScene" uid="uid://cidwsnulug6fl" path="res://scenes/box_ui.tscn" id="8_g71ie"] -[ext_resource type="Script" uid="uid://c4gfdpuc14mpq" path="res://src/cancel_button.gd" id="10_p7iul"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_as33y"] size = Vector2(128, 128) @@ -20,20 +18,25 @@ size = Vector2(128, 128) [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_usnyx"] size = Vector2(128, 64) -[node name="Inventory" type="Control"] +[node name="Inventory" type="Control" node_paths=PackedStringArray("carousel", "item_details")] layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 +offset_left = 2.0 +offset_right = 2.0 grow_horizontal = 2 grow_vertical = 2 size_flags_horizontal = 3 size_flags_vertical = 3 focus_mode = 2 theme = ExtResource("1_sr8g6") -script = ExtResource("1_as33y") -open_action = &"open_inventory" -close_action = &"ui_close_inventory" +script = ExtResource("2_g71ie") +inventory = ExtResource("2_as33y") +equipment = ExtResource("7_s887n") +inventory_item_scene = ExtResource("3_tg4gd") +carousel = NodePath("MarginContainer/Contents/MarginContainer/Carousel") +item_details = NodePath("MarginContainer/Contents/Details") [node name="ColorRect" type="ColorRect" parent="."] layout_mode = 1 @@ -59,25 +62,9 @@ alignment = 1 [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/Contents"] layout_mode = 2 -[node name="InventoryList" type="Control" parent="MarginContainer/Contents/MarginContainer" node_paths=PackedStringArray("carousel")] -custom_minimum_size = Vector2(0, 150) -layout_mode = 2 -size_flags_vertical = 3 -script = ExtResource("1_a0rpf") -inventory = ExtResource("2_as33y") -item_scene = ExtResource("3_tg4gd") -carousel = NodePath("Carousel") -metadata/_custom_type_script = "uid://qvoqvonnxwfc" - -[node name="Carousel" type="Container" parent="MarginContainer/Contents/MarginContainer/InventoryList"] +[node name="Carousel" type="Container" parent="MarginContainer/Contents/MarginContainer"] custom_minimum_size = Vector2(0, 100) -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -scale = Vector2(1, 1.01) +layout_mode = 2 script = ExtResource("5_uae8j") with_drag = true with_clamp = true @@ -85,39 +72,39 @@ item_size = Vector2(150, 100) item_seperation = 64 snap_behavior = 2 paging_requirement = 100 +manual_carousel_duration = 0.2 metadata/_custom_type_script = "uid://bpwbaanf6w65h" -[node name="Details" type="HBoxContainer" parent="MarginContainer/Contents" node_paths=PackedStringArray("viewport", "description_label", "action_menu")] +[node name="Details" type="HBoxContainer" parent="MarginContainer/Contents" node_paths=PackedStringArray("viewport", "description_label")] layout_mode = 2 size_flags_vertical = 3 -script = ExtResource("6_s887n") -equipment = ExtResource("7_s887n") -viewport = NodePath("ItemDisplay/VBoxContainer/Body/Display/SubViewport") -description_label = NodePath("ItemDescription/VBoxContainer/Body/MarginContainer/Label") -action_menu = NodePath("ItemDescription/VBoxContainer/Body/MarginContainer/Box") +script = ExtResource("4_yyk2a") +viewport = NodePath("ItemDisplay/Container/Content/SubViewport") +description_label = NodePath("ItemDescription/Container/Header/TitleContainer/Label") [node name="PlayerDetails" parent="MarginContainer/Contents/Details" instance=ExtResource("8_g71ie")] layout_mode = 2 -size_flags_horizontal = 3 -[node name="Body" parent="MarginContainer/Contents/Details/PlayerDetails/VBoxContainer" index="1"] -clip_contents = true - -[node name="PlayerInfo" type="VBoxContainer" parent="MarginContainer/Contents/Details/PlayerDetails/VBoxContainer/Body" index="0"] +[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/Contents/Details/PlayerDetails/Container/Content" index="0"] layout_mode = 2 -size_flags_horizontal = 3 +theme_override_constants/margin_left = 24 +theme_override_constants/margin_right = 24 -[node name="TextureRect" type="TextureRect" parent="MarginContainer/Contents/Details/PlayerDetails/VBoxContainer/Body/PlayerInfo"] +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/Contents/Details/PlayerDetails/Container/Content/MarginContainer"] +layout_mode = 2 +alignment = 1 + +[node name="TextureRect" type="TextureRect" parent="MarginContainer/Contents/Details/PlayerDetails/Container/Content/MarginContainer/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 4 texture = SubResource("PlaceholderTexture2D_as33y") -[node name="TextureRect2" type="TextureRect" parent="MarginContainer/Contents/Details/PlayerDetails/VBoxContainer/Body/PlayerInfo"] +[node name="TextureRect2" type="TextureRect" parent="MarginContainer/Contents/Details/PlayerDetails/Container/Content/MarginContainer/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 4 texture = SubResource("PlaceholderTexture2D_tg4gd") -[node name="TextureRect3" type="TextureRect" parent="MarginContainer/Contents/Details/PlayerDetails/VBoxContainer/Body/PlayerInfo"] +[node name="TextureRect3" type="TextureRect" parent="MarginContainer/Contents/Details/PlayerDetails/Container/Content/MarginContainer/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 4 texture = SubResource("PlaceholderTexture2D_usnyx") @@ -127,124 +114,44 @@ layout_mode = 2 size_flags_horizontal = 3 mouse_filter = 1 -[node name="Display" type="SubViewportContainer" parent="MarginContainer/Contents/Details/ItemDisplay/VBoxContainer/Body" index="0"] -layout_mode = 2 -size_flags_horizontal = 3 -stretch = true +[node name="Camera3D" type="Camera3D" parent="MarginContainer/Contents/Details/ItemDisplay/Container/Content" index="0"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2) -[node name="SubViewport" type="SubViewport" parent="MarginContainer/Contents/Details/ItemDisplay/VBoxContainer/Body/Display"] +[node name="SubViewport" type="SubViewport" parent="MarginContainer/Contents/Details/ItemDisplay/Container/Content" index="1"] own_world_3d = true transparent_bg = true handle_input_locally = false -size = Vector2i(374, 464) +size = Vector2i(374, 514) render_target_update_mode = 4 -[node name="Camera3D" type="Camera3D" parent="MarginContainer/Contents/Details/ItemDisplay/VBoxContainer/Body/Display/SubViewport"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2) - -[node name="DirectionalLight3D" type="DirectionalLight3D" parent="MarginContainer/Contents/Details/ItemDisplay/VBoxContainer/Body/Display/SubViewport"] -transform = Transform3D(0.71887, 0.431921, -0.544674, -0.0668683, 0.822874, 0.564277, 0.691921, -0.36922, 0.620421, 0, 0, 0) +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="MarginContainer/Contents/Details/ItemDisplay/Container/Content" index="2"] +transform = Transform3D(0.71887, 0.431921, -0.544675, -0.0668683, 0.822874, 0.564276, 0.691921, -0.36922, 0.620421, 0, 0, 0) [node name="ItemDescription" parent="MarginContainer/Contents/Details" instance=ExtResource("8_g71ie")] layout_mode = 2 size_flags_horizontal = 3 -focus_mode = 2 -[node name="VBoxContainer" parent="MarginContainer/Contents/Details/ItemDescription" index="0"] -mouse_filter = 2 - -[node name="Header" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer" index="0"] -mouse_filter = 2 - -[node name="TitleContainer" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Header" index="0"] -mouse_filter = 2 - -[node name="Body" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer" index="1"] -mouse_filter = 2 - -[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body" index="0"] +[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/Contents/Details/ItemDescription/Container/Content" index="0"] layout_mode = 2 -mouse_filter = 2 +theme_override_constants/margin_left = 8 +theme_override_constants/margin_top = 8 +theme_override_constants/margin_right = 8 +theme_override_constants/margin_bottom = 8 -[node name="Label" type="Label" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer"] +[node name="Label" type="Label" parent="MarginContainer/Contents/Details/ItemDescription/Container/Content/MarginContainer"] layout_mode = 2 -size_flags_vertical = 1 +size_flags_vertical = 3 autowrap_mode = 3 -[node name="Box" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer" instance=ExtResource("8_g71ie")] +[node name="ContextMenu" parent="MarginContainer/Contents/Details/ItemDescription/Container/Content/MarginContainer" instance=ExtResource("8_g71ie")] layout_mode = 2 size_flags_horizontal = 0 size_flags_vertical = 8 -focus_mode = 2 -[node name="VBoxContainer" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box" index="0"] -mouse_filter = 2 - -[node name="Header" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer" index="0"] -mouse_filter = 2 - -[node name="TitleContainer" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Header" index="0"] -mouse_filter = 2 - -[node name="Body" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer" index="1"] -mouse_filter = 2 - -[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body" index="0"] +[node name="Label" type="Label" parent="MarginContainer/Contents/Details/ItemDescription/Container/Content/MarginContainer/ContextMenu/Container/Content" index="0"] layout_mode = 2 -mouse_filter = 2 - -[node name="UseButton" type="Button" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body/VBoxContainer"] -layout_mode = 2 -focus_neighbor_left = NodePath(".") -focus_neighbor_top = NodePath(".") -focus_neighbor_right = NodePath(".") -focus_neighbor_bottom = NodePath("../CombineButton") -focus_next = NodePath("../CombineButton") -focus_previous = NodePath(".") -mouse_filter = 1 -mouse_default_cursor_shape = 2 -text = "USE" -alignment = 0 -script = ExtResource("10_p7iul") -metadata/_custom_type_script = "uid://c4gfdpuc14mpq" - -[node name="CombineButton" type="Button" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body/VBoxContainer"] -layout_mode = 2 -focus_neighbor_left = NodePath(".") -focus_neighbor_top = NodePath("../UseButton") -focus_neighbor_right = NodePath(".") -focus_neighbor_bottom = NodePath("../InspectButton") -focus_next = NodePath("../InspectButton") -focus_previous = NodePath("../UseButton") -mouse_filter = 1 -text = "COMBINE" -alignment = 0 -script = ExtResource("10_p7iul") -metadata/_custom_type_script = "uid://c4gfdpuc14mpq" - -[node name="InspectButton" type="Button" parent="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body/VBoxContainer"] -layout_mode = 2 -focus_neighbor_left = NodePath(".") -focus_neighbor_top = NodePath("../CombineButton") -focus_neighbor_right = NodePath(".") -focus_neighbor_bottom = NodePath(".") -focus_next = NodePath(".") -focus_previous = NodePath("../CombineButton") -mouse_filter = 1 -text = "INSPECT" -alignment = 0 -script = ExtResource("10_p7iul") -metadata/_custom_type_script = "uid://c4gfdpuc14mpq" - -[connection signal="item_focused" from="MarginContainer/Contents/MarginContainer/InventoryList" to="MarginContainer/Contents/Details" method="_on_updated"] -[connection signal="item_selected" from="MarginContainer/Contents/MarginContainer/InventoryList" to="MarginContainer/Contents/Details" method="_on_selected"] -[connection signal="hidden" from="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box" to="." method="grab_focus"] -[connection signal="visibility_changed" from="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box" to="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body/VBoxContainer/UseButton" method="grab_focus"] -[connection signal="pressed" from="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body/VBoxContainer/UseButton" to="MarginContainer/Contents/Details" method="use"] -[connection signal="pressed" from="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body/VBoxContainer/CombineButton" to="MarginContainer/Contents/Details" method="combine"] -[connection signal="pressed" from="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box/VBoxContainer/Body/VBoxContainer/InspectButton" to="MarginContainer/Contents/Details" method="inspect"] [editable path="MarginContainer/Contents/Details/PlayerDetails"] [editable path="MarginContainer/Contents/Details/ItemDisplay"] [editable path="MarginContainer/Contents/Details/ItemDescription"] -[editable path="MarginContainer/Contents/Details/ItemDescription/VBoxContainer/Body/MarginContainer/Box"] +[editable path="MarginContainer/Contents/Details/ItemDescription/Container/Content/MarginContainer/ContextMenu"] diff --git a/godot/scenes/inventory_item.tscn b/godot/scenes/inventory_item.tscn index b6d97f8..8e3381e 100644 --- a/godot/scenes/inventory_item.tscn +++ b/godot/scenes/inventory_item.tscn @@ -1,23 +1,14 @@ -[gd_scene load_steps=4 format=3 uid="uid://gn8k2ir47n1m"] +[gd_scene load_steps=3 format=3 uid="uid://gn8k2ir47n1m"] -[ext_resource type="Script" uid="uid://dt67n4jti376d" path="res://src/item_ui.gd" id="1_letey"] +[ext_resource type="Script" uid="uid://c2yaayl4msnf1" path="res://src/ui/item_ui.gd" id="1_letey"] [ext_resource type="PackedScene" uid="uid://cidwsnulug6fl" path="res://scenes/box_ui.tscn" id="1_y87vu"] -[ext_resource type="Theme" uid="uid://bb6tvyqikcf3r" path="res://scenes/box_ui.tres" id="3_y87vu"] -[node name="Item" node_paths=PackedStringArray("name_label", "icon_texture") instance=ExtResource("1_y87vu")] +[node name="Item" node_paths=PackedStringArray("_title_label", "_icon_texture") instance=ExtResource("1_y87vu")] script = ExtResource("1_letey") -name_label = NodePath("VBoxContainer/Header/TitleContainer/Label") -icon_texture = NodePath("VBoxContainer/Body/TextureRect") +_title_label = NodePath("Container/Header/TitleContainer/Label") +_icon_texture = NodePath("Container/Content/TextureRect") -[node name="Label" type="Label" parent="VBoxContainer/Header/TitleContainer" index="0"] -layout_mode = 2 -theme = ExtResource("3_y87vu") -theme_type_variation = &"BoxHeaderLabel" -text = "pistol" -vertical_alignment = 1 -uppercase = true - -[node name="TextureRect" type="TextureRect" parent="VBoxContainer/Body" index="0"] +[node name="TextureRect" type="TextureRect" parent="Container/Content" index="0"] layout_mode = 2 expand_mode = 3 stretch_mode = 5 diff --git a/godot/scenes/level.tscn b/godot/scenes/level.tscn index c1f9455..78fe7a1 100644 --- a/godot/scenes/level.tscn +++ b/godot/scenes/level.tscn @@ -1,14 +1,16 @@ -[gd_scene load_steps=17 format=3 uid="uid://dttyp3682enn7"] +[gd_scene load_steps=19 format=3 uid="uid://dttyp3682enn7"] [ext_resource type="PackedScene" uid="uid://crbrniwi6kd3p" path="res://scenes/player.tscn" id="1_2q6dc"] [ext_resource type="Script" uid="uid://csjccrhj5wnx7" path="res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd" id="2_klq6b"] -[ext_resource type="Script" uid="uid://ds8lef4lc6xuj" path="res://src/door.gd" id="2_w8frs"] +[ext_resource type="Script" uid="uid://ds8lef4lc6xuj" path="res://src/world/door.gd" id="2_w8frs"] [ext_resource type="Script" uid="uid://8umksf8e80fw" path="res://addons/phantom_camera/scripts/resources/tween_resource.gd" id="3_b121j"] -[ext_resource type="Script" uid="uid://dyghf5fq7s72x" path="res://src/interactable.gd" id="3_w8frs"] +[ext_resource type="Script" uid="uid://dyghf5fq7s72x" path="res://src/world/interactable.gd" id="3_w8frs"] [ext_resource type="Script" uid="uid://bd046eokvcnu2" path="res://addons/phantom_camera/scripts/phantom_camera_host/phantom_camera_host.gd" id="4_8c41q"] [ext_resource type="Script" uid="uid://pdpejp2xor23" path="res://src/persistence.gd" id="4_mx8sn"] [ext_resource type="Resource" uid="uid://cqfnwpmo4fyv4" path="res://resources/items/key.tres" id="7_8c41q"] +[ext_resource type="Script" uid="uid://35hnuxagjlo2" path="res://src/ui/ui_manager.gd" id="8_8iemx"] [ext_resource type="PackedScene" uid="uid://cn7tgd4y67wnd" path="res://scenes/inventory.tscn" id="8_b121j"] +[ext_resource type="Script" uid="uid://ct5na682hxc6g" path="res://src/ui/input_listener.gd" id="9_64w2a"] [ext_resource type="PackedScene" uid="uid://c0cf6jkxasplk" path="res://scenes/enemy.tscn" id="10_olg7q"] [ext_resource type="PackedScene" uid="uid://iwn3rk6leull" path="res://scenes/pistol_pickup.tscn" id="11_t1rx8"] @@ -89,34 +91,68 @@ shape = SubResource("BoxShape3D_mx8sn") [node name="Interactable" type="Node3D" parent="Door"] script = ExtResource("3_w8frs") -[node name="CanvasLayer" type="CanvasLayer" parent="."] +[node name="GameUI" type="CanvasLayer" parent="."] follow_viewport_enabled = true -[node name="Control" type="Control" parent="CanvasLayer"] +[node name="UIManager" type="Control" parent="GameUI" node_paths=PackedStringArray("inventory_menu", "context_menu")] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("8_8iemx") +inventory_menu = NodePath("Inventory") +context_menu = NodePath("Inventory/MarginContainer/Contents/Details/ItemDescription/Container/Content/MarginContainer/ContextMenu") +metadata/_custom_type_script = "uid://35hnuxagjlo2" + +[node name="Control" type="Control" parent="GameUI/UIManager"] layout_mode = 3 anchors_preset = 0 offset_right = 40.0 offset_bottom = 40.0 -[node name="Persistence" type="Node" parent="CanvasLayer/Control"] +[node name="Persistence" type="Node" parent="GameUI/UIManager/Control"] script = ExtResource("4_mx8sn") -[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/Control"] +[node name="HBoxContainer" type="HBoxContainer" parent="GameUI/UIManager/Control"] layout_mode = 0 offset_right = 40.0 offset_bottom = 40.0 -[node name="SaveButton" type="Button" parent="CanvasLayer/Control/HBoxContainer"] +[node name="SaveButton" type="Button" parent="GameUI/UIManager/Control/HBoxContainer"] layout_mode = 2 text = "Save" -[node name="LoadButton" type="Button" parent="CanvasLayer/Control/HBoxContainer"] +[node name="LoadButton" type="Button" parent="GameUI/UIManager/Control/HBoxContainer"] layout_mode = 2 text = "Load " -[node name="Inventory" parent="CanvasLayer" instance=ExtResource("8_b121j")] +[node name="Inventory" parent="GameUI/UIManager" instance=ExtResource("8_b121j")] visible = false +layout_mode = 1 + +[node name="InventoryListeners" type="Node" parent="GameUI"] + +[node name="OpenInventory" type="Control" parent="GameUI/InventoryListeners"] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("9_64w2a") +action = &"open_inventory" +method = 2 +metadata/_custom_type_script = "uid://ct5na682hxc6g" + +[node name="CloseInventory" type="Control" parent="GameUI/InventoryListeners"] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("9_64w2a") +action = &"ui_close_inventory" +metadata/_custom_type_script = "uid://ct5na682hxc6g" [node name="Enemy" parent="." instance=ExtResource("10_olg7q")] transform = Transform3D(1.75, 0, 0, 0, 1.75, 0, 0, 0, 1.75, 6, 0, 0) @@ -126,5 +162,12 @@ transform = Transform3D(-4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0, 1, 0, 2, [connection signal="opened" from="Door" to="Door" method="hide"] [connection signal="interacted" from="Door/Interactable" to="Door" method="_on_interact"] -[connection signal="pressed" from="CanvasLayer/Control/HBoxContainer/SaveButton" to="CanvasLayer/Control/Persistence" method="save" binds= ["save1.sav"]] -[connection signal="pressed" from="CanvasLayer/Control/HBoxContainer/LoadButton" to="CanvasLayer/Control/Persistence" method="load" binds= ["save1.sav"]] +[connection signal="pressed" from="GameUI/UIManager/Control/HBoxContainer/SaveButton" to="GameUI/UIManager/Control/Persistence" method="save" binds= ["save1.sav"]] +[connection signal="pressed" from="GameUI/UIManager/Control/HBoxContainer/LoadButton" to="GameUI/UIManager/Control/Persistence" method="load" binds= ["save1.sav"]] +[connection signal="pressed" from="GameUI/InventoryListeners/OpenInventory" to="GameUI/UIManager" method="open_inventory_menu"] + +[editable path="GameUI/UIManager/Inventory"] +[editable path="GameUI/UIManager/Inventory/MarginContainer/Contents/Details/PlayerDetails"] +[editable path="GameUI/UIManager/Inventory/MarginContainer/Contents/Details/ItemDisplay"] +[editable path="GameUI/UIManager/Inventory/MarginContainer/Contents/Details/ItemDescription"] +[editable path="GameUI/UIManager/Inventory/MarginContainer/Contents/Details/ItemDescription/Container/Content/MarginContainer/ContextMenu"] diff --git a/godot/scenes/player.tscn b/godot/scenes/player.tscn index 5dd1d46..33593d4 100644 --- a/godot/scenes/player.tscn +++ b/godot/scenes/player.tscn @@ -1,11 +1,11 @@ [gd_scene load_steps=49 format=3 uid="uid://crbrniwi6kd3p"] [ext_resource type="PackedScene" uid="uid://dpmbimh6m4ari" path="res://scenes/player_mesh.tscn" id="1_3vyb7"] -[ext_resource type="Script" uid="uid://50vv0ta67tgl" path="res://src/player.gd" id="1_qhqgy"] -[ext_resource type="Script" uid="uid://cngjp2wws4ld2" path="res://src/player_input.gd" id="3_dqkch"] -[ext_resource type="Script" uid="uid://c3wlcxy4vnm2i" path="res://src/interactor.gd" id="4_dqkch"] -[ext_resource type="Script" uid="uid://csjl56hf0fnoy" path="res://src/item_container.gd" id="5_qlg0r"] -[ext_resource type="Script" uid="uid://k1ihjmhj7ix" path="res://src/equipment_handler.gd" id="5_smehm"] +[ext_resource type="Script" uid="uid://50vv0ta67tgl" path="res://src/entity/player.gd" id="1_qhqgy"] +[ext_resource type="Script" uid="uid://cngjp2wws4ld2" path="res://src/entity/player_input.gd" id="3_dqkch"] +[ext_resource type="Script" uid="uid://c3wlcxy4vnm2i" path="res://src/world/interactor.gd" id="4_dqkch"] +[ext_resource type="Script" path="res://src/items/item_container.gd" id="5_qlg0r"] +[ext_resource type="Script" uid="uid://k1ihjmhj7ix" path="res://src/entity/equipment_handler.gd" id="5_smehm"] [ext_resource type="Resource" uid="uid://cxm3s081hnw8l" path="res://resources/player_equipment.tres" id="6_smehm"] [ext_resource type="Resource" uid="uid://bllq6ri54q3ne" path="res://resources/player_inventory.tres" id="6_tuyoq"] diff --git a/godot/src/attributes/ammo_attribute.gd b/godot/src/attributes/ammo_attribute.gd new file mode 100644 index 0000000..080864d --- /dev/null +++ b/godot/src/attributes/ammo_attribute.gd @@ -0,0 +1,5 @@ +class_name AmmoAttribute extends Attribute + +@export var ammo_type: Item +@export var max_capacity: int + diff --git a/godot/src/attributes/ammo_attribute.gd.uid b/godot/src/attributes/ammo_attribute.gd.uid new file mode 100644 index 0000000..2a3028f --- /dev/null +++ b/godot/src/attributes/ammo_attribute.gd.uid @@ -0,0 +1 @@ +uid://bbigpwchxitb5 diff --git a/godot/src/attributes/attribute.gd b/godot/src/attributes/attribute.gd new file mode 100644 index 0000000..4690775 --- /dev/null +++ b/godot/src/attributes/attribute.gd @@ -0,0 +1 @@ +class_name Attribute extends Resource diff --git a/godot/src/attributes/attribute.gd.uid b/godot/src/attributes/attribute.gd.uid new file mode 100644 index 0000000..940fcfc --- /dev/null +++ b/godot/src/attributes/attribute.gd.uid @@ -0,0 +1 @@ +uid://d1imxjix6ljul diff --git a/godot/src/attributes/combinable_attribute.gd b/godot/src/attributes/combinable_attribute.gd new file mode 100644 index 0000000..bdef349 --- /dev/null +++ b/godot/src/attributes/combinable_attribute.gd @@ -0,0 +1,2 @@ +class_name CombinableAttribute extends Attribute + diff --git a/godot/src/attributes/combinable_attribute.gd.uid b/godot/src/attributes/combinable_attribute.gd.uid new file mode 100644 index 0000000..a39576b --- /dev/null +++ b/godot/src/attributes/combinable_attribute.gd.uid @@ -0,0 +1 @@ +uid://dfkjh55qql76v diff --git a/godot/src/attributes/equippable_attribute.gd b/godot/src/attributes/equippable_attribute.gd new file mode 100644 index 0000000..71bce44 --- /dev/null +++ b/godot/src/attributes/equippable_attribute.gd @@ -0,0 +1,13 @@ +class_name EquippableAttribute extends Attribute + +enum Type { + PRIMARY, + SECONDARY +} + +@export var type: Type = Type.PRIMARY + +func equip_to(equipment: Equipment, item: Item): + match type: + Type.PRIMARY: equipment.primary = Option.some(item) + Type.SECONDARY: equipment.secondary = Option.some(item) diff --git a/godot/src/attributes/equippable_attribute.gd.uid b/godot/src/attributes/equippable_attribute.gd.uid new file mode 100644 index 0000000..d2aa654 --- /dev/null +++ b/godot/src/attributes/equippable_attribute.gd.uid @@ -0,0 +1 @@ +uid://c1y3loxtmkeg3 diff --git a/godot/src/attributes/usable_attribute.gd b/godot/src/attributes/usable_attribute.gd new file mode 100644 index 0000000..f64f162 --- /dev/null +++ b/godot/src/attributes/usable_attribute.gd @@ -0,0 +1,2 @@ +class_name UsableAttribute extends Attribute + diff --git a/godot/src/attributes/usable_attribute.gd.uid b/godot/src/attributes/usable_attribute.gd.uid new file mode 100644 index 0000000..69a84e0 --- /dev/null +++ b/godot/src/attributes/usable_attribute.gd.uid @@ -0,0 +1 @@ +uid://dpyiysj7aigc3 diff --git a/godot/src/damage_source.gd b/godot/src/entity/damage_source.gd similarity index 100% rename from godot/src/damage_source.gd rename to godot/src/entity/damage_source.gd diff --git a/godot/src/damage_source.gd.uid b/godot/src/entity/damage_source.gd.uid similarity index 100% rename from godot/src/damage_source.gd.uid rename to godot/src/entity/damage_source.gd.uid diff --git a/godot/src/equipment_handler.gd b/godot/src/entity/equipment_handler.gd similarity index 100% rename from godot/src/equipment_handler.gd rename to godot/src/entity/equipment_handler.gd diff --git a/godot/src/equipment_handler.gd.uid b/godot/src/entity/equipment_handler.gd.uid similarity index 100% rename from godot/src/equipment_handler.gd.uid rename to godot/src/entity/equipment_handler.gd.uid diff --git a/godot/src/health.gd b/godot/src/entity/health.gd similarity index 100% rename from godot/src/health.gd rename to godot/src/entity/health.gd diff --git a/godot/src/health.gd.uid b/godot/src/entity/health.gd.uid similarity index 100% rename from godot/src/health.gd.uid rename to godot/src/entity/health.gd.uid diff --git a/godot/src/player.gd b/godot/src/entity/player.gd similarity index 99% rename from godot/src/player.gd rename to godot/src/entity/player.gd index 01ba1c6..5d67e60 100644 --- a/godot/src/player.gd +++ b/godot/src/entity/player.gd @@ -67,3 +67,5 @@ func on_before_load(): func on_load(data: Dictionary): position = data.position rotation = data.rotation + + diff --git a/godot/src/player.gd.uid b/godot/src/entity/player.gd.uid similarity index 100% rename from godot/src/player.gd.uid rename to godot/src/entity/player.gd.uid diff --git a/godot/src/player_input.gd b/godot/src/entity/player_input.gd similarity index 100% rename from godot/src/player_input.gd rename to godot/src/entity/player_input.gd diff --git a/godot/src/player_input.gd.uid b/godot/src/entity/player_input.gd.uid similarity index 100% rename from godot/src/player_input.gd.uid rename to godot/src/entity/player_input.gd.uid diff --git a/godot/src/input_listener.gd b/godot/src/input_listener.gd deleted file mode 100644 index 74553e7..0000000 --- a/godot/src/input_listener.gd +++ /dev/null @@ -1,29 +0,0 @@ -class_name InputListener extends Control - -enum ActionEvent { - Pressed, - Released -} - -signal opened -signal closed - -@export var input_event: ActionEvent -@export var open_action: StringName -@export var close_action: StringName - -func _is_active(event: InputEvent, action: StringName) -> bool: - match input_event: - ActionEvent.Pressed: return event.is_action_pressed(action) - ActionEvent.Released: return event.is_action_released(action) - _: return false - -func _unhandled_input(event: InputEvent) -> void: - if _is_active(event, open_action): - accept_event() - opened.emit() - -func _gui_input(event: InputEvent) -> void: - if _is_active(event, close_action): - accept_event() - closed.emit() diff --git a/godot/src/item_cointainer.gd.uid b/godot/src/item_cointainer.gd.uid deleted file mode 100644 index 1761500..0000000 --- a/godot/src/item_cointainer.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bbkm8bt2mrq1c diff --git a/godot/src/item_details_ui.gd b/godot/src/item_details_ui.gd deleted file mode 100644 index fb431d2..0000000 --- a/godot/src/item_details_ui.gd +++ /dev/null @@ -1,67 +0,0 @@ -class_name ItemDetailsUI extends HBoxContainer - -@export var equipment: Equipment -@export var viewport: SubViewport -@export var description_label: Label -@export var action_menu: Control - -var current_item: Option = Option.none - -var _displayed_item: Node3D -var _default_description: String - -func _ready() -> void: - action_menu.hide() - _default_description = description_label.text - -func _set_default(): - if _displayed_item != null: - viewport.remove_child(_displayed_item) - _displayed_item.queue_free() - description_label.text = _default_description - -func _on_updated(item: Option): - current_item = item - if item.is_some(): - var _item: Item = item.unwrap() - match _item.create_preview(): - var x when x.is_some(): - _displayed_item = x.unwrap() - viewport.add_child(_displayed_item) - _: _set_default() - description_label.text = _item.description - else: - _set_default() - -func _on_selected(_item: Item): - action_menu.show() - -func _notification(what: int) -> void: - if what == NOTIFICATION_FOCUS_EXIT: - action_menu.hide() - -func _is_equip(item: Item) -> bool: - return is_instance_of(item, EquippableItem) - -func _already_equipped(item: Item) -> bool: - return equipment.is_equipped(item) - -func use(): - if current_item.is_some(): - var item = current_item.unwrap() - if _is_equip(item): - if _already_equipped(item): - equipment.unequip_item(item) - else: - equipment.equip(item) - else: - item.use() - action_menu.hide() - -func combine(): - current_item.inspect(func(x): x.combine()) - action_menu.hide() - -func inspect(): - current_item.inspect(func(x): x.inspect()) - action_menu.hide() diff --git a/godot/src/equipment.gd b/godot/src/items/equipment.gd similarity index 56% rename from godot/src/equipment.gd rename to godot/src/items/equipment.gd index 0ed6585..044a3ca 100644 --- a/godot/src/equipment.gd +++ b/godot/src/items/equipment.gd @@ -1,11 +1,11 @@ class_name Equipment extends Resource -signal unequipped_primary(equipment: EquippableItem) -signal equipped_primary(equipment: EquippableItem) -signal unequipped_secondary(equipment: EquippableItem) -signal equipped_secondary(equipment: EquippableItem) +signal unequipped_primary(equipment: Item) +signal equipped_primary(equipment: Item) +signal unequipped_secondary(equipment: Item) +signal equipped_secondary(equipment: Item) -@export var _primary: EquippableItem +@export var _primary: Item var primary: Option: get: return Option.from(_primary) @@ -17,7 +17,7 @@ func _unequip_primary(): _primary = null unequipped_primary.emit(previous) -func _equip_primary(item: EquippableItem): +func _equip_primary(item: Item): if _primary != null: _unequip_primary() @@ -31,7 +31,7 @@ func set_primary(item: Option): _equip_primary(x.unwrap()) _: _unequip_primary() -@export var _secondary: EquippableItem +@export var _secondary: Item var secondary: Option: get: return Option.from(_secondary) @@ -43,7 +43,7 @@ func _unequip_secondary(): _secondary = null unequipped_secondary.emit(previous) -func _equip_secondary(item: EquippableItem): +func _equip_secondary(item: Item): if _secondary != null: _unequip_secondary() @@ -67,24 +67,24 @@ func _ready(): if _secondary != null: _equip_secondary(_secondary) -func equip(item: EquippableItem): +func equip(item: Item): match item.type: - EquippableItem.EquipmentType.PRIMARY: primary = Option.some(item) - EquippableItem.EquipmentType.SECONDARY: secondary = Option.some(item) + EquippableAttribute.Type.PRIMARY: primary = Option.some(item) + EquippableAttribute.Type.SECONDARY: secondary = Option.some(item) -func unequip(equip_type: EquippableItem.EquipmentType): +func unequip(equip_type: EquippableAttribute.Type): match equip_type: - EquippableItem.EquipmentType.PRIMARY: primary = Option.none - EquippableItem.EquipmentType.SECONDARY:secondary = Option.none + EquippableAttribute.Type.PRIMARY: primary = Option.none + EquippableAttribute.Type.SECONDARY:secondary = Option.none -func unequip_item(item: EquippableItem): +func unequip_item(item: Item): equipped_to(item).inspect(unequip) -func is_equipped(item: EquippableItem) -> bool: +func is_equipped(item: Item) -> bool: return equipped_to(item).is_some() -func equipped_to(item: EquippableItem) -> Option: +func equipped_to(item: Item) -> Option: match item.type: - EquippableItem.EquipmentType.PRIMARY when item == _primary: return Option.some(EquippableItem.EquipmentType.PRIMARY) - EquippableItem.EquipmentType.SECONDARY when item == _secondary: return Option.some(EquippableItem.EquipmentType.SECONDARY) + EquippableAttribute.Type.PRIMARY when item == _primary: return Option.some(EquippableItem.EquipmentType.PRIMARY) + EquippableAttribute.Type.SECONDARY when item == _secondary: return Option.some(EquippableItem.EquipmentType.SECONDARY) return Option.none diff --git a/godot/src/equipment.gd.uid b/godot/src/items/equipment.gd.uid similarity index 100% rename from godot/src/equipment.gd.uid rename to godot/src/items/equipment.gd.uid diff --git a/godot/src/equippable_item.gd b/godot/src/items/equippable_item.gd similarity index 62% rename from godot/src/equippable_item.gd rename to godot/src/items/equippable_item.gd index d60faa4..c749e88 100644 --- a/godot/src/equippable_item.gd +++ b/godot/src/items/equippable_item.gd @@ -6,6 +6,14 @@ enum EquipmentType { } @export var type: EquipmentType = EquipmentType.PRIMARY +@export var ammo_type: Item +@export var ammo_capacity: int + +var uses_ammo: bool: + get: return ammo_type != null + +var display_ammo: bool: + get: return ammo_capacity < 2 func is_primary() -> bool: return type == EquipmentType.PRIMARY diff --git a/godot/src/equippable_item.gd.uid b/godot/src/items/equippable_item.gd.uid similarity index 100% rename from godot/src/equippable_item.gd.uid rename to godot/src/items/equippable_item.gd.uid diff --git a/godot/src/inventory.gd b/godot/src/items/inventory.gd similarity index 100% rename from godot/src/inventory.gd rename to godot/src/items/inventory.gd diff --git a/godot/src/inventory.gd.uid b/godot/src/items/inventory.gd.uid similarity index 100% rename from godot/src/inventory.gd.uid rename to godot/src/items/inventory.gd.uid diff --git a/godot/src/item.gd b/godot/src/items/item.gd similarity index 64% rename from godot/src/item.gd rename to godot/src/items/item.gd index 68da390..6dc33e9 100644 --- a/godot/src/item.gd +++ b/godot/src/items/item.gd @@ -6,6 +6,7 @@ class_name Item extends Resource @export var icon: Texture2D @export var scene: PackedScene @export var preview_scene: PackedScene +@export var attributes: Array[Attribute] = [] func _to_string() -> String: var icon_path = _resource_path_name(icon) @@ -29,9 +30,19 @@ func create() -> Option: func create_preview() -> Option: return _create(preview_scene) +func inspect(): + pass -func combine(_with: Item) -> bool: +func has_attribute(type: Variant) -> bool: + for value in attributes: + if is_instance_of(value, type): + return true return false + return ListIterator.from_array(attributes).any(func(x): return is_instance_of(x, type)) + +func get_attribute(type: Variant) -> Option: + return ListIterator.from_array(attributes).find(func(x): is_instance_of(x, type)) + +func get_attributes(type: Variant) -> Iterator: + return ListIterator.from_array(attributes).filter(func(x): is_instance_of(x, type)) -func use() -> bool: - return false diff --git a/godot/src/item.gd.uid b/godot/src/items/item.gd.uid similarity index 100% rename from godot/src/item.gd.uid rename to godot/src/items/item.gd.uid diff --git a/godot/src/item_container.gd b/godot/src/items/item_container.gd similarity index 100% rename from godot/src/item_container.gd rename to godot/src/items/item_container.gd diff --git a/godot/src/item_container.gd.uid b/godot/src/items/item_container.gd.uid similarity index 100% rename from godot/src/item_container.gd.uid rename to godot/src/items/item_container.gd.uid diff --git a/godot/src/item_instance.gd b/godot/src/items/item_instance.gd similarity index 100% rename from godot/src/item_instance.gd rename to godot/src/items/item_instance.gd diff --git a/godot/src/item_instance.gd.uid b/godot/src/items/item_instance.gd.uid similarity index 100% rename from godot/src/item_instance.gd.uid rename to godot/src/items/item_instance.gd.uid diff --git a/godot/src/item_pickup.gd b/godot/src/items/item_pickup.gd similarity index 100% rename from godot/src/item_pickup.gd rename to godot/src/items/item_pickup.gd diff --git a/godot/src/item_pickup.gd.uid b/godot/src/items/item_pickup.gd.uid similarity index 100% rename from godot/src/item_pickup.gd.uid rename to godot/src/items/item_pickup.gd.uid diff --git a/godot/src/node_ext.gd b/godot/src/node_ext.gd index 39f3b18..70493a6 100644 --- a/godot/src/node_ext.gd +++ b/godot/src/node_ext.gd @@ -1,38 +1,48 @@ class_name NodeExt class NodeChildIterator: - var _node: Node - var _include_internal: bool - var _index: int - var _length: int + var _node: Node + var _include_internal: bool + var _index: int + var _length: int - func _init(node: Node, include_internal: bool) -> void: - _node = node - _include_internal = include_internal - _index = 0 - _length = node.get_child_count(include_internal) + func _init(node: Node, include_internal: bool) -> void: + _node = node + _include_internal = include_internal + _index = 0 + _length = node.get_child_count(include_internal) - func _continue() -> bool: - return (_index < _length) + func _continue() -> bool: + return (_index < _length) - func _iter_init(_iter: Array) -> bool: - _index = 0 - return _continue() + func _iter_init(_iter: Array) -> bool: + _index = 0 + return _continue() - func _iter_next(_iter: Array) -> bool: - _index += 1 - return _continue() + func _iter_next(_iter: Array) -> bool: + _index += 1 + return _continue() - func _iter_get(_iter: Variant) -> Variant: - return _node.get_child(_index, _include_internal) + func _iter_get(_iter: Variant) -> Variant: + return _node.get_child(_index, _include_internal) static func find_child(node: Node, predicate: Callable, include_internal: bool = false) -> Option: - for child in NodeChildIterator.new(node, include_internal): - if predicate.call(child): - return Option.some(child) - return Option.none + for child in NodeChildIterator.new(node, include_internal): + if predicate.call(child): + return Option.some(child) + return Option.none + +static func find_children(node: Node, predicate: Callable, include_internal: bool = false) -> Array[Node]: + var results: Array[Node] = [] + for child in NodeChildIterator.new(node, include_internal): + if predicate.call(child): + results.append(child) + return results + +static func find_children_variant(node: Node, variant: Variant, include_internal: bool = false) -> Array[Node]: + return find_children(node, func(child: Node) -> bool: return is_instance_of(child, variant), include_internal) static func find_child_variant(node: Node, variant: Variant, include_internal: bool = false) -> Option: - for child in NodeChildIterator.new(node, include_internal): - if is_instance_of(child, variant): - return Option.some(child) - return Option.none + for child in NodeChildIterator.new(node, include_internal): + if is_instance_of(child, variant): + return Option.some(child) + return Option.none diff --git a/godot/src/root_control.gd b/godot/src/root_control.gd deleted file mode 100644 index be0cd41..0000000 --- a/godot/src/root_control.gd +++ /dev/null @@ -1,23 +0,0 @@ -class_name RootControl extends InputListener - -func _ready() -> void: - if self.focus_mode == Control.FOCUS_NONE: - self.focus_mode = Control.FOCUS_ALL - - opened.connect(open) - closed.connect(close) - - if visible: - grab_focus() - -func open(): - show() - grab_focus() - -func close(): - hide() - release_focus() - -func _gui_input(event: InputEvent) -> void: - super(event) - KCUtils.propagate_input_event(self, "_gui_input", event, false) diff --git a/godot/src/ui/box.gd b/godot/src/ui/box.gd new file mode 100644 index 0000000..dd21504 --- /dev/null +++ b/godot/src/ui/box.gd @@ -0,0 +1,7 @@ +class_name Box extends PanelContainer + +@export var title_label: Label +@export var body_container: Control + +func add_content(content: Control) -> void: + body_container.add_child(content) diff --git a/godot/src/ui/box.gd.uid b/godot/src/ui/box.gd.uid new file mode 100644 index 0000000..2c0dd08 --- /dev/null +++ b/godot/src/ui/box.gd.uid @@ -0,0 +1 @@ +uid://bnumwlio6adb8 diff --git a/godot/src/cancel_button.gd b/godot/src/ui/cancel_button.gd similarity index 77% rename from godot/src/cancel_button.gd rename to godot/src/ui/cancel_button.gd index 1811b1d..b22dacb 100644 --- a/godot/src/cancel_button.gd +++ b/godot/src/ui/cancel_button.gd @@ -6,4 +6,4 @@ func _gui_input(event: InputEvent) -> void: if event.is_action_pressed(cancel_action): accept_event() release_focus() - KCUtils.notify(get_parent(), NOTIFICATION_FOCUS_EXIT, true) + K.notify(get_parent(), NOTIFICATION_FOCUS_EXIT, true) diff --git a/godot/src/cancel_button.gd.uid b/godot/src/ui/cancel_button.gd.uid similarity index 100% rename from godot/src/cancel_button.gd.uid rename to godot/src/ui/cancel_button.gd.uid diff --git a/godot/src/ui/context_menu.gd b/godot/src/ui/context_menu.gd new file mode 100644 index 0000000..4c2146a --- /dev/null +++ b/godot/src/ui/context_menu.gd @@ -0,0 +1,7 @@ +class_name ContextMenu extends Control + +signal requested_close + +func set_options_for(item: Item): + pass + diff --git a/godot/src/ui/context_menu.gd.uid b/godot/src/ui/context_menu.gd.uid new file mode 100644 index 0000000..2750875 --- /dev/null +++ b/godot/src/ui/context_menu.gd.uid @@ -0,0 +1 @@ +uid://c71q7htypy0i8 diff --git a/godot/src/h_item_list.gd b/godot/src/ui/h_item_list.gd similarity index 100% rename from godot/src/h_item_list.gd rename to godot/src/ui/h_item_list.gd diff --git a/godot/src/h_item_list.gd.uid b/godot/src/ui/h_item_list.gd.uid similarity index 100% rename from godot/src/h_item_list.gd.uid rename to godot/src/ui/h_item_list.gd.uid diff --git a/godot/src/index_carousel.gd b/godot/src/ui/index_carousel.gd similarity index 100% rename from godot/src/index_carousel.gd rename to godot/src/ui/index_carousel.gd diff --git a/godot/src/index_carousel.gd.uid b/godot/src/ui/index_carousel.gd.uid similarity index 100% rename from godot/src/index_carousel.gd.uid rename to godot/src/ui/index_carousel.gd.uid diff --git a/godot/src/ui/input_group_listener.gd b/godot/src/ui/input_group_listener.gd new file mode 100644 index 0000000..8bafdb7 --- /dev/null +++ b/godot/src/ui/input_group_listener.gd @@ -0,0 +1,20 @@ +class_name InputGroupListener extends Node + +signal pressed +signal released + +var listeners: Array[InputListener] + +func _ready() -> void: + listeners.assign(NodeExt.find_children_variant(self, InputListener)) + + for listener in listeners: + listener.pressed.connect(_on_pressed) + listener.released.connect(_on_released) + +func _on_pressed() -> void: + pressed.emit() + +func _on_released() -> void: + released.emit() + diff --git a/godot/src/root_control.gd.uid b/godot/src/ui/input_group_listener.gd.uid similarity index 100% rename from godot/src/root_control.gd.uid rename to godot/src/ui/input_group_listener.gd.uid diff --git a/godot/src/ui/input_listener.gd b/godot/src/ui/input_listener.gd new file mode 100644 index 0000000..02dc6b5 --- /dev/null +++ b/godot/src/ui/input_listener.gd @@ -0,0 +1,57 @@ +class_name InputListener extends Control + +enum InputMethod { + GUI_INPUT, + INPUT, + UNHANDLED_INPUT, + UNHANDLED_KEY_INPUT +} + +signal pressed +signal released + +@export var action: StringName +@export var method: InputMethod = InputMethod.INPUT + +func _ready() -> void: + set_process_input(false) + set_process_unhandled_input(false) + set_process_unhandled_key_input(false) + + set_enabled(true) + +func set_enabled(enabled: bool) -> void: + match method: + InputMethod.GUI_INPUT | InputMethod.INPUT: set_process_input(enabled) + InputMethod.UNHANDLED_INPUT: set_process_unhandled_input(enabled) + InputMethod.UNHANDLED_KEY_INPUT: set_process_unhandled_key_input(enabled) + +func enable() -> void: + set_enabled(true) + +func disable() -> void: + set_enabled(false) + +func _test_action(event: InputEvent): + if event.is_action_pressed(action): + if pressed.has_connections(): + pressed.emit() + accept_event() + elif event.is_action_released(action): + if released.has_connections(): + released.emit() + accept_event() + +func _gui_input(event: InputEvent) -> void: + if method == InputMethod.GUI_INPUT: + _test_action(event) + +func _input(event: InputEvent) -> void: + if method == InputMethod.INPUT: + _test_action(event) + +func _unhandled_input(event: InputEvent) -> void: + _test_action(event) + +func _unhandled_key_input(event: InputEvent) -> void: + _test_action(event) diff --git a/godot/src/input_listener.gd.uid b/godot/src/ui/input_listener.gd.uid similarity index 100% rename from godot/src/input_listener.gd.uid rename to godot/src/ui/input_listener.gd.uid diff --git a/godot/src/ui/inventory_screen.gd b/godot/src/ui/inventory_screen.gd new file mode 100644 index 0000000..259bfad --- /dev/null +++ b/godot/src/ui/inventory_screen.gd @@ -0,0 +1,79 @@ +class_name InventoryScreen extends Control + +signal item_selected(item: Item) +signal requested_close + +@export_group("Dependencies") +@export var inventory: Inventory +@export var equipment: Equipment + +@export_group("Carousel") +@export var inventory_item_scene: PackedScene +@export var carousel: IndexCarousel +@export var item_details: ItemDetailUI + + +func _ready() -> void: + _connect_signals() + +func _connect_signals() -> void: + inventory.updated.connect(_build_carousel) + carousel.index_changed.connect(_on_item_changed) + +enum Direction { + Right = 1, + Left = -1 +} + +func _gui_input(event: InputEvent) -> void: + if event.is_action_pressed(PlayerInput.UIAction.Right): + move_carousel(Direction.Right) + accept_event() + elif event.is_action_pressed(PlayerInput.UIAction.Left): + move_carousel(Direction.Left) + accept_event() + elif event.is_action_pressed(PlayerInput.UIAction.Accept): + _items().nth(carousel.current_index).inspect(item_selected.emit) + accept_event() + +func _items() -> Iterator: + return inventory.iter().map(func(x): return x.value.item) + +func _build_carousel() -> void: + K.remove_children(carousel) + + var empty_iter = Iterator.repeat(null).take(inventory.empty_slots) + var item_iter = ListIterator.from_array(inventory.items.values().map(func(x): return x.item)) + + for item in item_iter.fuse(empty_iter): + var scene = inventory_item_scene.instantiate() + var option = Option.from(item) + bind_item(scene, option) + carousel.add_child(scene) + +func bind_item(node: Node, item: Option) -> void: + if node.has_method('bind'): + node.bind(item) + +func move_carousel(delta: int): + var next_index = carousel.get_carousel_index() + delta + carousel.go_to_index(next_index) + +func close(): + requested_close.emit() + +func _on_item_changed(index: int) -> void: + item_details.set_item(_items().nth(index)) + +func _use() -> void: + pass + +func _equip() -> void: + pass + +func _combine() -> void: + pass + +func _inspect() -> void: + pass + diff --git a/godot/src/ui/inventory_screen.gd.uid b/godot/src/ui/inventory_screen.gd.uid new file mode 100644 index 0000000..b2be9b1 --- /dev/null +++ b/godot/src/ui/inventory_screen.gd.uid @@ -0,0 +1 @@ +uid://b7j7weoa8tikm diff --git a/godot/src/ui/inventory_screen.uid b/godot/src/ui/inventory_screen.uid new file mode 100644 index 0000000..51cb6f5 --- /dev/null +++ b/godot/src/ui/inventory_screen.uid @@ -0,0 +1 @@ +uid://bjwhkpqabr7sg diff --git a/godot/src/inventory_ui.gd b/godot/src/ui/inventory_ui.gd similarity index 97% rename from godot/src/inventory_ui.gd rename to godot/src/ui/inventory_ui.gd index 90e9f68..b25f24e 100644 --- a/godot/src/inventory_ui.gd +++ b/godot/src/ui/inventory_ui.gd @@ -21,7 +21,7 @@ func _on_item_changed(index: int) -> void: _: item_focused.emit(Option.none) func _build_carousel() -> void: - KCUtils.remove_children(carousel) + K.remove_children(carousel) var empty_iter = Iterator.repeat(null).take(inventory.empty_slots) var item_iter = ListIterator.from_array(inventory.items.values().map(func(x): return x.item)) diff --git a/godot/src/inventory_ui.gd.uid b/godot/src/ui/inventory_ui.gd.uid similarity index 100% rename from godot/src/inventory_ui.gd.uid rename to godot/src/ui/inventory_ui.gd.uid diff --git a/godot/src/ui/item_detail_ui.gd b/godot/src/ui/item_detail_ui.gd new file mode 100644 index 0000000..606ae25 --- /dev/null +++ b/godot/src/ui/item_detail_ui.gd @@ -0,0 +1,35 @@ +class_name ItemDetailUI extends HBoxContainer + +@export var viewport: SubViewport +@export var description_label: Label + +var current_item: Option = Option.none + +var _displayed_item: Node3D +var _default_description: String + +func _ready() -> void: + _default_description = description_label.text + +func _set_default(): + if _displayed_item != null: + viewport.remove_child(_displayed_item) + _displayed_item.queue_free() + description_label.text = _default_description + +func set_item(item: Option): + current_item = item + if item.is_some(): + var _item: Item = item.unwrap() + match _item.create_preview(): + var x when x.is_some(): + _displayed_item = x.unwrap() + viewport.add_child(_displayed_item) + _: _set_default() + description_label.text = _item.description + else: + clear_item() + + +func clear_item(): + _set_default() diff --git a/godot/src/item_details_ui.gd.uid b/godot/src/ui/item_detail_ui.gd.uid similarity index 100% rename from godot/src/item_details_ui.gd.uid rename to godot/src/ui/item_detail_ui.gd.uid diff --git a/godot/src/item_ui.gd b/godot/src/ui/item_slot_ui.gd similarity index 92% rename from godot/src/item_ui.gd rename to godot/src/ui/item_slot_ui.gd index 9a203f2..67662d0 100644 --- a/godot/src/item_ui.gd +++ b/godot/src/ui/item_slot_ui.gd @@ -1,4 +1,4 @@ -class_name ItemUI extends Control +class_name ItemSlotUI extends Control @export var name_label: Label @export var icon_texture: TextureRect diff --git a/godot/src/item_ui.gd.uid b/godot/src/ui/item_slot_ui.gd.uid similarity index 100% rename from godot/src/item_ui.gd.uid rename to godot/src/ui/item_slot_ui.gd.uid diff --git a/godot/src/ui/item_ui.gd b/godot/src/ui/item_ui.gd new file mode 100644 index 0000000..b30d7a8 --- /dev/null +++ b/godot/src/ui/item_ui.gd @@ -0,0 +1,27 @@ +class_name ItemUI extends Control + +@export var _title_label: Label +@export var _icon_texture: TextureRect + +var _default_title: String +var _default_icon: Texture2D + +func _ready() -> void: + _default_title = _title_label.text + _default_icon = _icon_texture.texture + +func _set_default() -> void: + _title_label.text = _default_title + _icon_texture.texture = _default_icon + +func bind(item: Option) -> void: + match item: + var x when x.is_some(): + print(x) + var _item = x.unwrap() + _title_label.text = _item.name + _icon_texture.texture = _item.icon + _: _set_default() + +func clear() -> void: + _set_default() diff --git a/godot/src/ui/item_ui.gd.uid b/godot/src/ui/item_ui.gd.uid new file mode 100644 index 0000000..6a4d2eb --- /dev/null +++ b/godot/src/ui/item_ui.gd.uid @@ -0,0 +1 @@ +uid://c2yaayl4msnf1 diff --git a/godot/src/ring_buffer.gd b/godot/src/ui/ring_buffer.gd similarity index 100% rename from godot/src/ring_buffer.gd rename to godot/src/ui/ring_buffer.gd diff --git a/godot/src/ring_buffer.gd.uid b/godot/src/ui/ring_buffer.gd.uid similarity index 100% rename from godot/src/ring_buffer.gd.uid rename to godot/src/ui/ring_buffer.gd.uid diff --git a/godot/src/ui/ui_manager.gd b/godot/src/ui/ui_manager.gd new file mode 100644 index 0000000..b4fcae2 --- /dev/null +++ b/godot/src/ui/ui_manager.gd @@ -0,0 +1,159 @@ +class_name UIManager extends Control + +@export var inventory_menu: Control +@export var context_menu: Control + +class StackFrame extends RefCounted: + var root: Control + var children: Array[Control] = [] + + func _init(element: Control) -> void: + root = element + +var stack: Array[StackFrame] = [] + +func _ready() -> void: + if inventory_menu.has_signal('requested_close'): + inventory_menu.requested_close.connect(close_inventory_menu) + #if context_menu.has_signal('requested_close'): + # context_menu.requested_close.connect(close_context_menu) + +func get_current_frame() -> Option: + if stack.is_empty(): return Option.none + else: return Option.some(stack.back()) + +func _focus_current_frame(frame: StackFrame) -> void: + if not frame.children.is_empty(): + frame.children.back().grab_focus() + else: + frame.root.grab_focus() + +func focus_current_frame() -> void: + get_current_frame().inspect(_focus_current_frame) + +func clamp_rect(rect: Rect2) -> Rect2: + var result = Rect2(rect) + var viewport_rect = get_viewport().get_visible_rect() + + if result.end.x > viewport_rect.size.x: + result.x = viewport_rect.size.x - result.size.x + + result.position.x = maxf(0, rect.position.x) + + if result.end.y > viewport_rect.size.y: + result.y = viewport_rect.size.y - result.size.y + + result.position.y = maxf(0, rect.position.y) + + return result + +func open_inventory_menu() -> void: + if is_open(inventory_menu): + return + var new_frame = StackFrame.new(inventory_menu) + stack.append(new_frame) + inventory_menu.show() + inventory_menu.grab_focus() + +func close_inventory_menu() -> void: + _handle_root_ui_closed(inventory_menu) + +func open_context_menu(_position: Vector2, content: Control) -> void: + if stack.is_empty(): + push_error("can't open context menu. no active windows") + return + + var current_frame = get_current_frame() + + var clamped_rect = clamp_rect(Rect2(_position, context_menu.size)) + context_menu.global_position = clamped_rect.position + context_menu.set_content(content) + + current_frame.children.append(context_menu) + + context_menu.show() + context_menu.grab_focus() + +func close_context_menu() -> void: + _handle_child_closed(context_menu) + +func is_open(element: Control) -> bool: + for i in range(stack.size()): + if stack[i].root == element: + return true + return false + +func _remove_element(element: Control) -> void: + var frame_to_close: StackFrame = null + var frame_index: int = -1 + + for i in range(stack.size()): + if stack[i].root == element: + frame_to_close = stack[i] + frame_index = i + break + + if frame_to_close: + _close_frame(frame_to_close, frame_index) + else: + push_warning("'%s' requested to be closed but was not found as a root UI in any stack frame." % element.name) + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(PlayerInput.UIAction.Cancel): + var current_frame_option = get_current_frame() + if current_frame_option.is_some(): + var current_frame = current_frame_option.unwrap() + if not current_frame.children.is_empty(): + var top_child = current_frame.children.back() + if top_child.has_method("cancel"): + top_child.handle_cancel() + else: + top_child.hide() + current_frame.children.pop_back() + focus_current_frame() + else: + var root_element = current_frame.root + if root_element.has_method("cancel"): + root_element.handle_cancel() + else: + root_element.hide() + stack.pop_back() + focus_current_frame() + + accept_event() + +func _handle_child_closed(child: Control) -> void: + if stack.is_empty(): return + var current_frame = get_current_frame().unwrap() + + if not current_frame.children.is_empty() and current_frame.children.back() == child: + current_frame.children.pop_back() + child.hide() + focus_current_frame() + else: + push_warning("A child window '%s' requested to be closed but was not the top-most child of the current stack frame." % child.name) + +func _handle_root_ui_closed(root_ui: Control) -> void: + var frame_index = -1 + for i in range(stack.size()): + if stack[i].root == root_ui: + frame_index = i + break + + if frame_index != -1: + _close_frame(stack[frame_index], frame_index) + else: + push_warning("Root UI '%s' closed but its frame was not found in the stack." % root_ui.name) + + +func _close_frame(frame: StackFrame, index: int) -> void: + frame.root.hide() + for i in range(frame.children.size() -1, -1, -1): + var child = frame.children[i] + if is_instance_valid(child): + child.hide() + frame.children.clear() + + stack.remove_at(index) + focus_current_frame() + diff --git a/godot/src/ui/ui_manager.gd.uid b/godot/src/ui/ui_manager.gd.uid new file mode 100644 index 0000000..ba3f5e4 --- /dev/null +++ b/godot/src/ui/ui_manager.gd.uid @@ -0,0 +1 @@ +uid://35hnuxagjlo2 diff --git a/godot/src/window_ui.gd b/godot/src/window_ui.gd deleted file mode 100644 index e69de29..0000000 diff --git a/godot/src/window_ui.gd.uid b/godot/src/window_ui.gd.uid deleted file mode 100644 index b819dd3..0000000 --- a/godot/src/window_ui.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bxd483uvo31jf diff --git a/godot/src/door.gd b/godot/src/world/door.gd similarity index 100% rename from godot/src/door.gd rename to godot/src/world/door.gd diff --git a/godot/src/door.gd.uid b/godot/src/world/door.gd.uid similarity index 100% rename from godot/src/door.gd.uid rename to godot/src/world/door.gd.uid diff --git a/godot/src/interactable.gd b/godot/src/world/interactable.gd similarity index 100% rename from godot/src/interactable.gd rename to godot/src/world/interactable.gd diff --git a/godot/src/interactable.gd.uid b/godot/src/world/interactable.gd.uid similarity index 100% rename from godot/src/interactable.gd.uid rename to godot/src/world/interactable.gd.uid diff --git a/godot/src/interactor.gd b/godot/src/world/interactor.gd similarity index 100% rename from godot/src/interactor.gd rename to godot/src/world/interactor.gd diff --git a/godot/src/interactor.gd.uid b/godot/src/world/interactor.gd.uid similarity index 100% rename from godot/src/interactor.gd.uid rename to godot/src/world/interactor.gd.uid diff --git a/godot/src/raycast.gd b/godot/src/world/raycast.gd similarity index 100% rename from godot/src/raycast.gd rename to godot/src/world/raycast.gd diff --git a/godot/src/raycast.gd.uid b/godot/src/world/raycast.gd.uid similarity index 100% rename from godot/src/raycast.gd.uid rename to godot/src/world/raycast.gd.uid diff --git a/godot/src/usable.gd b/godot/src/world/usable.gd similarity index 100% rename from godot/src/usable.gd rename to godot/src/world/usable.gd diff --git a/godot/src/usable.gd.uid b/godot/src/world/usable.gd.uid similarity index 100% rename from godot/src/usable.gd.uid rename to godot/src/world/usable.gd.uid