Best way to add items in ItemList

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Rzymon

Hello, I’m trying to create inventory. I’m using ItemList for this.

I see that people use *.png or *.tex files for each item, when they adding items to ItemList.

I wanted to do something more flexible for items (IMHO It’s inefficient for me, to have 100 separated *.png files if you have 100 items in your project). I saved few items in one (f.e.) items.png file, and I created TileSet using Sprite nodes and setting Texture region for each Sprite and I exported all to TileSet.

Next I created scene with ItemList and I wrote this:

extends Node

onready var itemList = get_node("Panel/ItemList")
onready var items = preload("res://Core/Scenes/Tilesets/Items32x32.tres")

func _ready():
	
	itemList.max_columns = 9
	itemList.fixed_icon_size = Vector2(32,32)
	itemList.icon_mode = ItemList.ICON_MODE_TOP
	itemList.select_mode = ItemList.SELECT_SINGLE
	itemList.same_column_width = true
	var item = items.tile_get_texture(0) #Spirte with ID=0 from TileSet
	
	itemList.add_item("", item, true)

But when I play scene I have whole *png but scaled to one item slot.

How can I get one tile from TileSet to put it to my ItemList? Or maybe I’m doing something wrong, so what is the best way to store multiple items texture?

Did you define the sprites and corresponding rect information inside your Tileset scene as it is explained here?

rolfpancake | 2018-02-19 13:01

Yes. This is my scene which I exported to TileSet. Every Sprite has it’s own region set in properties.

Rzymon | 2018-02-19 13:13

Alright, I know it’s been a year since this question but I just had the same issue and was able to solve it

First I wanna start off by saying that my inventory UI system is based on the fact that the logic will pass to it an array of instances of scenes (the items scenes).

The item scene has a Sprite Node which taxes the ENTIRE TILESET TEXTURE and grabs a region from it, so that it takes the single sprite that corresponds to the particular item (which is the proper to handle sprites anyway, screw dealing with hundreds of png’s lol)

Now, considering the above I did this:

func setInventory(items):
var id = 0
for item in items:
	var itemSprite = item.get_node("Sprite")
	$CanvasLayer/Container/ItemList.add_icon_item(itemSprite.texture)
	$CanvasLayer/Container/ItemList.set_item_icon_region(id, itemSprite.region_rect)
	id += 1

Solanich | 2019-02-10 01:45

:bust_in_silhouette: Reply From: rolfpancake

I wasn’t able to implement this idea with a TileSet because when trying to get the Texture of a specific tile you will always receive the referenced base Texture without an enabled region.

I was able to implement this with an AtlasTexture. Create an AtlasTexture Resource, load your Image as atlas and save this atlas resource. Then you can use it via code like this:

extends Node

onready var itemList = get_node("itemlist")
onready var items = preload("res://atlas.tres")
onready var items_amount = 4
onready var items_width = 50
onready var items_height = 50

func _ready():
	itemList.max_columns = 9
	itemList.fixed_icon_size = Vector2(32,32)
	itemList.icon_mode = ItemList.ICON_MODE_TOP
	itemList.select_mode = ItemList.SELECT_SINGLE
	itemList.same_column_width = true

	for i in range(items_amount):
		var item = items.duplicate()
		item.set_region(Rect2(i * items_width, 0, items_width, items_height))
		itemList.add_item("", item, true)

Basically you are instancing AtlasTextures based on your pre-defined AtlasTexture. And these instanced Textures get region-settings based on your constructed Image. This can be adapted with enums or maybe a json that you can store different sizes and use mixed offsets inside your image. But here I only looked at the case when using a constant icon width/height which are placed next to each other.

(I used the Image provided in the TileSet Tutorial.)

Thanks a lot! It helped me a lot :wink:
Anyway i decided to put items icons in separate image files, but I’m not sure if it’s the best way having a huge amount of small files or only one, but huge file.

Rzymon | 2018-03-17 13:24

:bust_in_silhouette: Reply From: Solanich

Alright, I know it’s been a year since this question but I just had the same issue and was able to solve it

First I wanna start off by saying that my inventory UI system is based on the fact that the logic will pass to it an array of instances of scenes (the items scenes).

The item scene has a Sprite Node which taxes the ENTIRE TILESET TEXTURE and grabs a region from it, so that it takes the single sprite that corresponds to the particular item (which is the proper to handle sprites anyway, screw dealing with hundreds of png’s lol)

Now, considering the above I did this:

func setInventory(items):
var id = 0
for item in items:
	var itemSprite = item.get_node("Sprite")
	$CanvasLayer/Container/ItemList.add_icon_item(itemSprite.texture)
	$CanvasLayer/Container/ItemList.set_item_icon_region(id, itemSprite.region_rect)
	id += 1