├── .gitignore ├── .gitattributes ├── Assets ├── Item1.png ├── Item2.png ├── Item3.png ├── Item4.png ├── inventory_texture.png ├── inventory_texture.png~ ├── Item1.png.import ├── Item2.png.import ├── Item3.png.import ├── Item4.png.import └── inventory_texture.png.import ├── main.tscn ├── Data └── Item_data.json ├── item.tscn ├── slot.tscn ├── icon.svg.import ├── DataHandler.gd ├── slot.gd ├── project.godot ├── item.gd ├── export_presets.cfg ├── icon.svg ├── inventory.tscn └── inventory.gd /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /Assets/Item1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrAlphredo/Grid-Inventory-Tutorial-1/HEAD/Assets/Item1.png -------------------------------------------------------------------------------- /Assets/Item2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrAlphredo/Grid-Inventory-Tutorial-1/HEAD/Assets/Item2.png -------------------------------------------------------------------------------- /Assets/Item3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrAlphredo/Grid-Inventory-Tutorial-1/HEAD/Assets/Item3.png -------------------------------------------------------------------------------- /Assets/Item4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrAlphredo/Grid-Inventory-Tutorial-1/HEAD/Assets/Item4.png -------------------------------------------------------------------------------- /Assets/inventory_texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrAlphredo/Grid-Inventory-Tutorial-1/HEAD/Assets/inventory_texture.png -------------------------------------------------------------------------------- /Assets/inventory_texture.png~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrAlphredo/Grid-Inventory-Tutorial-1/HEAD/Assets/inventory_texture.png~ -------------------------------------------------------------------------------- /main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://bi0dj1n12x32l"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://0nqqxacxuayc" path="res://inventory.tscn" id="1_5gysd"] 4 | 5 | [node name="Main" type="Node2D"] 6 | 7 | [node name="Inventory" parent="." instance=ExtResource("1_5gysd")] 8 | -------------------------------------------------------------------------------- /Data/Item_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "1": { 3 | "Name": "Item1", 4 | "Value": 10, 5 | "Grid": "0,0/0,1/-1,0" 6 | }, 7 | "2": { 8 | "Name": "Item2", 9 | "Value": 20, 10 | "Grid": "0,0/0,1" 11 | }, 12 | "3": { 13 | "Name": "Item3", 14 | "Value": 30, 15 | "Grid": "0,0/1,0" 16 | }, 17 | "4": { 18 | "Name": "Item4", 19 | "Value": 40, 20 | "Grid": "0,0" 21 | } 22 | } -------------------------------------------------------------------------------- /item.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://cgm6b2tpenwep"] 2 | 3 | [ext_resource type="Script" path="res://item.gd" id="1_im0vf"] 4 | 5 | [node name="Item" type="Node2D"] 6 | script = ExtResource("1_im0vf") 7 | 8 | [node name="Icon" type="TextureRect" parent="."] 9 | anchors_preset = 8 10 | anchor_left = 0.5 11 | anchor_top = 0.5 12 | anchor_right = 0.5 13 | anchor_bottom = 0.5 14 | offset_left = -20.0 15 | offset_top = -20.0 16 | offset_right = 20.0 17 | offset_bottom = 20.0 18 | grow_horizontal = 2 19 | grow_vertical = 2 20 | -------------------------------------------------------------------------------- /slot.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bwwf7txdqilrc"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://dd3ppdnkci0bj" path="res://Assets/inventory_texture.png" id="1_cv2pd"] 4 | [ext_resource type="Script" path="res://slot.gd" id="2_g5ktd"] 5 | 6 | [node name="Slot" type="TextureRect"] 7 | custom_minimum_size = Vector2(50, 50) 8 | offset_right = 50.0 9 | offset_bottom = 50.0 10 | texture = ExtResource("1_cv2pd") 11 | expand_mode = 1 12 | script = ExtResource("2_g5ktd") 13 | 14 | [node name="StatusFilter" type="ColorRect" parent="."] 15 | layout_mode = 1 16 | anchors_preset = 15 17 | anchor_right = 1.0 18 | anchor_bottom = 1.0 19 | grow_horizontal = 2 20 | grow_vertical = 2 21 | color = Color(1, 0, 0, 0) 22 | -------------------------------------------------------------------------------- /Assets/Item1.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c64vv0rhihshv" 6 | path="res://.godot/imported/Item1.png-cf66492ce77965df0a8bac72163de29c.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Item1.png" 14 | dest_files=["res://.godot/imported/Item1.png-cf66492ce77965df0a8bac72163de29c.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Item2.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://162ghk8254m3" 6 | path="res://.godot/imported/Item2.png-a2cf896e918b0ceb1a052973b4512596.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Item2.png" 14 | dest_files=["res://.godot/imported/Item2.png-a2cf896e918b0ceb1a052973b4512596.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Item3.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cjj80i8b4i205" 6 | path="res://.godot/imported/Item3.png-8406a7113a8dd022d483a9832660a323.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Item3.png" 14 | dest_files=["res://.godot/imported/Item3.png-8406a7113a8dd022d483a9832660a323.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Item4.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cu25votopfa5" 6 | path="res://.godot/imported/Item4.png-bb36020680f504d4d6a4b569558d0492.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Item4.png" 14 | dest_files=["res://.godot/imported/Item4.png-bb36020680f504d4d6a4b569558d0492.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/inventory_texture.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dd3ppdnkci0bj" 6 | path="res://.godot/imported/inventory_texture.png-7c0b4ec318a44c69b9d17cbdf76b88c5.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/inventory_texture.png" 14 | dest_files=["res://.godot/imported/inventory_texture.png-7c0b4ec318a44c69b9d17cbdf76b88c5.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cblgu82cjarcp" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /DataHandler.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | var item_data := {} 4 | var item_grid_data := {} 5 | @onready var item_data_path = "res://Data/Item_data.json" 6 | 7 | # Called when the node enters the scene tree for the first time. 8 | func _ready(): 9 | load_data(item_data_path) 10 | set_grid_data() 11 | 12 | #load the data file 13 | func load_data(path : String) -> void: 14 | if not FileAccess.file_exists(path): 15 | print("Item Data file not found") 16 | var item_data_file = FileAccess.open(path, FileAccess.READ) 17 | item_data = JSON.parse_string(item_data_file.get_as_text()) 18 | item_data_file.close() 19 | #print(item_data) #check value 20 | 21 | #process the json and put the grid information into accessable array format for iterating 22 | func set_grid_data() -> void: 23 | for item in item_data.keys(): 24 | var temp_grid_array := [] 25 | for point in item_data[item]["Grid"].split("/"): 26 | temp_grid_array.push_back(point.split(",")) 27 | item_grid_data[item] = temp_grid_array 28 | #print(item_grid_data) #check values 29 | 30 | -------------------------------------------------------------------------------- /slot.gd: -------------------------------------------------------------------------------- 1 | extends TextureRect 2 | 3 | signal slot_entered(slot) 4 | signal slot_exited(slot) 5 | 6 | @onready var filter = $StatusFilter 7 | 8 | var slot_ID 9 | var is_hovering:=false 10 | enum States {DEFAULT, TAKEN, FREE} 11 | var state = States.DEFAULT 12 | var item_stored = null 13 | 14 | 15 | # Called when the node enters the scene tree for the first time. 16 | func _ready(): 17 | pass # Replace with function body. 18 | 19 | func set_color(a_state = States.DEFAULT) -> void : 20 | match a_state: 21 | States.DEFAULT: 22 | filter.color = Color(Color.WHITE, 0.0) 23 | States.TAKEN: 24 | filter.color = Color(Color.RED, 0.2) 25 | States.FREE: 26 | filter.color = Color(Color.GREEN, 0.2) 27 | 28 | # Called every frame. 'delta' is the elapsed time since the previous frame. 29 | func _process(delta): 30 | if get_global_rect().has_point(get_global_mouse_position()): 31 | if not is_hovering: 32 | is_hovering = true 33 | emit_signal("slot_entered",self) 34 | else: 35 | if is_hovering: 36 | is_hovering = false 37 | emit_signal("slot_exited",self) 38 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="Grid Inventory Tutorial 1" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.0", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [autoload] 19 | 20 | DataHandler="*res://DataHandler.gd" 21 | 22 | [display] 23 | 24 | window/stretch/mode="canvas_items" 25 | 26 | [input] 27 | 28 | mouse_rightclick={ 29 | "deadzone": 0.5, 30 | "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(284, 10),"global_position":Vector2(288, 53),"factor":1.0,"button_index":2,"pressed":true,"double_click":false,"script":null) 31 | ] 32 | } 33 | mouse_leftclick={ 34 | "deadzone": 0.5, 35 | "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(235, 27),"global_position":Vector2(239, 70),"factor":1.0,"button_index":1,"pressed":true,"double_click":false,"script":null) 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /item.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | @onready var IconRect_path = $Icon 4 | 5 | var item_ID : int 6 | var item_grids := [] 7 | var selected = false 8 | var grid_anchor = null 9 | 10 | # Called when the node enters the scene tree for the first time. 11 | func _ready(): 12 | pass 13 | 14 | 15 | # Called every frame. 'delta' is the elapsed time since the previous frame. 16 | func _process(delta): 17 | if selected: 18 | global_position = lerp(global_position, get_global_mouse_position(), 25 * delta) 19 | 20 | func load_item(a_ItemID : int) -> void: 21 | var Icon_path = "res://Assets/" + DataHandler.item_data[str(a_ItemID)]["Name"] + ".png" 22 | IconRect_path.texture = load(Icon_path) 23 | for grid in DataHandler.item_grid_data[str(a_ItemID)]: 24 | var converter_array := [] 25 | for i in grid : 26 | converter_array.push_back(int(i)) 27 | item_grids.push_back(converter_array) 28 | #print(item_grids) 29 | 30 | #rotate 90 degress CW 31 | func rotate_item(): 32 | for grid in item_grids: 33 | var temp_y = grid[0] 34 | grid[0] = -grid[1] 35 | grid[1] = temp_y 36 | rotation_degrees += 90 37 | if rotation_degrees>=360: 38 | rotation_degrees = 0 39 | 40 | func _snap_to(destination): 41 | var tween = get_tree().create_tween() 42 | #separate cases to avoid snapping errors 43 | if int(rotation_degrees) % 180 == 0: 44 | destination += IconRect_path.size/2 45 | else: 46 | var temp_xy_switch = Vector2(IconRect_path.size.y,IconRect_path.size.x) 47 | destination += temp_xy_switch/2 48 | tween.tween_property(self, "global_position", destination, 0.15).set_trans(Tween.TRANS_SINE) 49 | selected = false 50 | -------------------------------------------------------------------------------- /export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Windows Desktop" 4 | platform="Windows Desktop" 5 | runnable=true 6 | dedicated_server=false 7 | custom_features="" 8 | export_filter="all_resources" 9 | include_filter="" 10 | exclude_filter="" 11 | export_path="exports/Grid Inventory.exe" 12 | encryption_include_filters="" 13 | encryption_exclude_filters="" 14 | encrypt_pck=false 15 | encrypt_directory=false 16 | script_encryption_key="" 17 | 18 | [preset.0.options] 19 | 20 | custom_template/debug="" 21 | custom_template/release="" 22 | debug/export_console_script=1 23 | binary_format/embed_pck=false 24 | texture_format/bptc=true 25 | texture_format/s3tc=true 26 | texture_format/etc=false 27 | texture_format/etc2=false 28 | binary_format/architecture="x86_64" 29 | codesign/enable=false 30 | codesign/identity_type=0 31 | codesign/identity="" 32 | codesign/password="" 33 | codesign/timestamp=true 34 | codesign/timestamp_server_url="" 35 | codesign/digest_algorithm=1 36 | codesign/description="" 37 | codesign/custom_options=PackedStringArray() 38 | application/modify_resources=false 39 | application/icon="" 40 | application/console_wrapper_icon="" 41 | application/icon_interpolation=4 42 | application/file_version="" 43 | application/product_version="" 44 | application/company_name="" 45 | application/product_name="" 46 | application/file_description="" 47 | application/copyright="" 48 | application/trademarks="" 49 | ssh_remote_deploy/enabled=false 50 | ssh_remote_deploy/host="user@host_ip" 51 | ssh_remote_deploy/port="22" 52 | ssh_remote_deploy/extra_args_ssh="" 53 | ssh_remote_deploy/extra_args_scp="" 54 | ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}' 55 | $action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}' 56 | $trigger = New-ScheduledTaskTrigger -Once -At 00:00 57 | $settings = New-ScheduledTaskSettingsSet 58 | $task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings 59 | Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true 60 | Start-ScheduledTask -TaskName godot_remote_debug 61 | while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 } 62 | Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue" 63 | ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue 64 | Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue 65 | Remove-Item -Recurse -Force '{temp_dir}'" 66 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /inventory.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://0nqqxacxuayc"] 2 | 3 | [ext_resource type="Script" path="res://inventory.gd" id="1_jolrh"] 4 | 5 | [node name="Inventory" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 15 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | grow_horizontal = 2 11 | grow_vertical = 2 12 | script = ExtResource("1_jolrh") 13 | 14 | [node name="Background" type="ColorRect" parent="."] 15 | layout_mode = 0 16 | offset_left = 129.0 17 | offset_top = 62.0 18 | offset_right = 549.0 19 | offset_bottom = 582.0 20 | color = Color(0.14902, 0.0823529, 0.0823529, 1) 21 | 22 | [node name="MarginContainer" type="MarginContainer" parent="Background"] 23 | layout_mode = 1 24 | anchors_preset = 15 25 | anchor_right = 1.0 26 | anchor_bottom = 1.0 27 | grow_horizontal = 2 28 | grow_vertical = 2 29 | 30 | [node name="VBoxContainer" type="VBoxContainer" parent="Background/MarginContainer"] 31 | layout_mode = 2 32 | 33 | [node name="Header" type="HBoxContainer" parent="Background/MarginContainer/VBoxContainer"] 34 | custom_minimum_size = Vector2(0, 100) 35 | layout_mode = 2 36 | size_flags_vertical = 2 37 | theme_override_constants/separation = 0 38 | 39 | [node name="Button_Spawn" type="Button" parent="Background/MarginContainer/VBoxContainer/Header"] 40 | custom_minimum_size = Vector2(200, 70) 41 | layout_mode = 2 42 | size_flags_horizontal = 6 43 | size_flags_vertical = 4 44 | theme_override_font_sizes/font_size = 20 45 | text = "Spawn Item" 46 | 47 | [node name="Add_slot" type="Button" parent="Background/MarginContainer/VBoxContainer/Header"] 48 | custom_minimum_size = Vector2(100, 50) 49 | layout_mode = 2 50 | size_flags_horizontal = 6 51 | size_flags_vertical = 4 52 | text = "Add Slot" 53 | 54 | [node name="ScrollContainer" type="ScrollContainer" parent="Background/MarginContainer/VBoxContainer"] 55 | custom_minimum_size = Vector2(0, 420) 56 | layout_mode = 2 57 | size_flags_vertical = 3 58 | 59 | [node name="GridContainer" type="GridContainer" parent="Background/MarginContainer/VBoxContainer/ScrollContainer"] 60 | layout_mode = 2 61 | theme_override_constants/h_separation = 0 62 | theme_override_constants/v_separation = 0 63 | columns = 8 64 | 65 | [node name="Background2" type="ColorRect" parent="."] 66 | visible = false 67 | layout_mode = 0 68 | offset_left = 700.0 69 | offset_top = 62.0 70 | offset_right = 1120.0 71 | offset_bottom = 582.0 72 | color = Color(0.14902, 0.0823529, 0.0823529, 1) 73 | 74 | [node name="MarginContainer" type="MarginContainer" parent="Background2"] 75 | layout_mode = 1 76 | anchors_preset = 15 77 | anchor_right = 1.0 78 | anchor_bottom = 1.0 79 | grow_horizontal = 2 80 | grow_vertical = 2 81 | 82 | [node name="VBoxContainer" type="VBoxContainer" parent="Background2/MarginContainer"] 83 | layout_mode = 2 84 | 85 | [node name="Header" type="HBoxContainer" parent="Background2/MarginContainer/VBoxContainer"] 86 | custom_minimum_size = Vector2(0, 100) 87 | layout_mode = 2 88 | size_flags_vertical = 2 89 | theme_override_constants/separation = 0 90 | 91 | [node name="Button_Spawn" type="Button" parent="Background2/MarginContainer/VBoxContainer/Header"] 92 | custom_minimum_size = Vector2(200, 70) 93 | layout_mode = 2 94 | size_flags_horizontal = 6 95 | size_flags_vertical = 4 96 | theme_override_font_sizes/font_size = 20 97 | text = "Spawn Item" 98 | 99 | [node name="ScrollContainer" type="ScrollContainer" parent="Background2/MarginContainer/VBoxContainer"] 100 | custom_minimum_size = Vector2(0, 420) 101 | layout_mode = 2 102 | size_flags_vertical = 3 103 | 104 | [node name="GridContainer" type="GridContainer" parent="Background2/MarginContainer/VBoxContainer/ScrollContainer"] 105 | layout_mode = 2 106 | theme_override_constants/h_separation = 1 107 | theme_override_constants/v_separation = 1 108 | columns = 8 109 | 110 | [connection signal="pressed" from="Background/MarginContainer/VBoxContainer/Header/Button_Spawn" to="." method="_on_button_spawn_pressed"] 111 | [connection signal="pressed" from="Background/MarginContainer/VBoxContainer/Header/Add_slot" to="." method="_on_add_slot_pressed"] 112 | [connection signal="pressed" from="Background2/MarginContainer/VBoxContainer/Header/Button_Spawn" to="." method="_on_button_spawn_pressed"] 113 | -------------------------------------------------------------------------------- /inventory.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | @onready var slot_scene = preload("res://slot.tscn") 4 | @onready var grid_container = $Background/MarginContainer/VBoxContainer/ScrollContainer/GridContainer 5 | @onready var item_scene = preload("res://item.tscn") 6 | @onready var scroll_container = $Background/MarginContainer/VBoxContainer/ScrollContainer 7 | @onready var col_count = grid_container.columns #save column number 8 | @onready var grid_container2 = $Background2/MarginContainer/VBoxContainer/ScrollContainer/GridContainer 9 | 10 | var grid_array := [] 11 | var item_held = null 12 | var current_slot = null 13 | var can_place := false 14 | var icon_anchor : Vector2 15 | # Called when the node enters the scene tree for the first time. 16 | func _ready(): 17 | for i in range(14): 18 | create_slot() 19 | 20 | 21 | 22 | # Called every frame. 'delta' is the elapsed time since the previous frame. 23 | func _process(delta): 24 | if item_held: 25 | if Input.is_action_just_pressed("mouse_rightclick"): 26 | rotate_item() 27 | 28 | if Input.is_action_just_pressed("mouse_leftclick"): 29 | if scroll_container.get_global_rect().has_point(get_global_mouse_position()): 30 | place_item() 31 | else: 32 | if Input.is_action_just_pressed("mouse_leftclick"): 33 | if scroll_container.get_global_rect().has_point(get_global_mouse_position()): 34 | pick_item() 35 | 36 | 37 | func create_slot(): 38 | var new_slot = slot_scene.instantiate() 39 | new_slot.slot_ID = grid_array.size() 40 | grid_container.add_child(new_slot) 41 | grid_array.push_back(new_slot) 42 | new_slot.slot_entered.connect(_on_slot_mouse_entered) 43 | new_slot.slot_exited.connect(_on_slot_mouse_exited) 44 | pass 45 | 46 | 47 | func _on_slot_mouse_entered(a_Slot): 48 | icon_anchor = Vector2(10000,100000) 49 | current_slot = a_Slot 50 | if item_held: 51 | check_slot_availability(current_slot) 52 | set_grids.call_deferred(current_slot) 53 | 54 | func _on_slot_mouse_exited(a_Slot): 55 | clear_grid() 56 | 57 | if not grid_container.get_global_rect().has_point(get_global_mouse_position()): 58 | current_slot = null 59 | 60 | func _on_button_spawn_pressed(): 61 | var new_item = item_scene.instantiate() 62 | add_child(new_item) 63 | new_item.load_item(randi_range(1,4)) #randomize this for different items to spawn 64 | new_item.selected = true 65 | item_held = new_item 66 | 67 | 68 | func check_slot_availability(a_Slot): 69 | for grid in item_held.item_grids: 70 | var grid_to_check = a_Slot.slot_ID + grid[0] + grid[1] * col_count 71 | var line_switch_check = a_Slot.slot_ID % col_count + grid[0] 72 | if line_switch_check < 0 or line_switch_check >= col_count: 73 | can_place = false 74 | return 75 | if grid_to_check < 0 or grid_to_check >= grid_array.size(): 76 | can_place = false 77 | return 78 | if grid_array[grid_to_check].state == grid_array[grid_to_check].States.TAKEN: 79 | can_place = false 80 | return 81 | 82 | can_place = true 83 | 84 | func set_grids(a_Slot): 85 | for grid in item_held.item_grids: 86 | var grid_to_check = a_Slot.slot_ID + grid[0] + grid[1] * col_count 87 | if grid_to_check < 0 or grid_to_check >= grid_array.size(): 88 | continue 89 | #make sure the check don't wrap around boarders 90 | var line_switch_check = a_Slot.slot_ID % col_count + grid[0] 91 | if line_switch_check <0 or line_switch_check >= col_count: 92 | continue 93 | 94 | if can_place: 95 | grid_array[grid_to_check].set_color(grid_array[grid_to_check].States.FREE) 96 | #save anchor for snapping 97 | if grid[1] < icon_anchor.x: icon_anchor.x = grid[1] 98 | if grid[0] < icon_anchor.y: icon_anchor.y = grid[0] 99 | 100 | else: 101 | grid_array[grid_to_check].set_color(grid_array[grid_to_check].States.TAKEN) 102 | 103 | func clear_grid(): 104 | for grid in grid_array: 105 | grid.set_color(grid.States.DEFAULT) 106 | 107 | func rotate_item(): 108 | item_held.rotate_item() 109 | clear_grid() 110 | if current_slot: 111 | _on_slot_mouse_entered(current_slot) 112 | 113 | func place_item(): 114 | if not can_place or not current_slot: 115 | return #put indication of placement failed, sound or visual here 116 | 117 | #for changing scene tree 118 | item_held.get_parent().remove_child(item_held) 119 | grid_container.add_child(item_held) 120 | item_held.global_position = get_global_mouse_position() 121 | #### 122 | var calculated_grid_id = current_slot.slot_ID + icon_anchor.x * col_count + icon_anchor.y 123 | item_held._snap_to(grid_array[calculated_grid_id].global_position) 124 | print(calculated_grid_id) 125 | item_held.grid_anchor = current_slot 126 | for grid in item_held.item_grids: 127 | var grid_to_check = current_slot.slot_ID + grid[0] + grid[1] * col_count 128 | grid_array[grid_to_check].state = grid_array[grid_to_check].States.TAKEN 129 | grid_array[grid_to_check].item_stored = item_held 130 | 131 | #put item into a data storage here 132 | 133 | item_held = null 134 | clear_grid() 135 | 136 | func pick_item(): 137 | if not current_slot or not current_slot.item_stored: 138 | return 139 | item_held = current_slot.item_stored 140 | item_held.selected = true 141 | #move node in the scene tree 142 | item_held.get_parent().remove_child(item_held) 143 | add_child(item_held) 144 | item_held.global_position = get_global_mouse_position() 145 | #### 146 | 147 | for grid in item_held.item_grids: 148 | var grid_to_check = item_held.grid_anchor.slot_ID + grid[0] + grid[1] * col_count # use grid anchor instead of current slot to prevent bug 149 | grid_array[grid_to_check].state = grid_array[grid_to_check].States.FREE 150 | grid_array[grid_to_check].item_stored = null 151 | 152 | check_slot_availability(current_slot) 153 | set_grids.call_deferred(current_slot) 154 | 155 | 156 | 157 | 158 | func _on_add_slot_pressed(): 159 | create_slot() 160 | --------------------------------------------------------------------------------