+1 vote

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?

in Engine by (13 points)

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

Yes. This is my scene which I exported to TileSet. Every Sprite has it's own region set in properties.
enter image description here

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

2 Answers

0 votes

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.)

by (1,024 points)

Thanks a lot! It helped me a lot ;)
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.

+1 vote

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
by (23 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.