Tool script for importing a tileset from an image

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By batmanasb
:warning: Old Version Published before Godot 3 was released.

I drew a tileset in a png image and want to make a tileset scene out of it. The only issue is that each tile is 16x16 pixels and there are 16x16 tiles, so manually setting the region rect for each sprite would take way to much time.

Does anyone have a tool script for this or know how to go about making one? I’m thinking something that simply duplicates a Sprite again and again in a double for loop and sets the region to something like (x*16, y*16, x*16+16, y*16+16). Then I can add in the StaticBody2D and NavPoly nodes myself

While I wait, I’ll start trying to figure this out and post an answer if I figure it out.

:bust_in_silhouette: Reply From: batmanasb

After a bit of research I managed to make this script that you can attach to the root node of the tileset scene and check the “reset” box to generate a numbered sprite for each tile.
Note: only works with square images and doesn’t delete previously created sprites (to protect against accidental clicks). It’s okay to have blank tiles as long as the tileset image is square… or you can edit my script if you don’t like blank tiles. It’s not as elegant as the plugin scripts I found, but it works fine for my needs.

tool
extends Node

export(bool) var reset = false setget onReset

#config
var tileSize = 16
var tileCount = 16
var spritesheet = preload("res://map/tileset.png")


func _ready():
	pass


func onReset(isTriggered):
	if(isTriggered):
		reset = false

		for y in range(tileCount):
			for x in range(tileCount):
				var tile = Sprite.new()
				add_child(tile)
				tile.set_owner(self)
				tile.set_name(str(x+y*tileCount))
				tile.set_texture(spritesheet)
				tile.set_region(true)
				tile.set_region_rect(Rect2(x*tileSize, y*tileSize, tileSize, tileSize))
				tile.set_pos(Vector2(x*tileSize+tileSize/2, y*tileSize+tileSize/2))

This took some time to figure out but it was well worth it in order to not do this by hand!

Edit: added the offset (tileSize/2) so the sprites line up correctly

How do you get this to work? I’ve set up a new scene with a root Node, attached this script and then checked the Reset variable on/off a few times… this should cause them to be added, right? What am I missing?

EDIT: I had to close/re-open the scene and they got added. heh.

olsonjeffery | 2016-05-13 18:01

Yeah, basically tool scripts require the editor to be restarted after any change.

batmanasb | 2016-05-14 06:29

Thanks for the code batmanasb!
I made a small change so that the tileCount is needed anymore, it detects the amount of x/y tiles using the image width/height:

tool
extends Node

export(bool) var reset = false setget onReset

#config
var tileSize = 16
var spritesheet = preload("res://map/tileset.png")

func _ready():
	pass

func onReset(isTriggered):
	if (isTriggered):
		reset = false
		var w = spritesheet.get_width() / tileSize
		var h = spritesheet.get_height() / tileSize

		for y in range(h):
			for x in range(w):
				var tile = Sprite.new()
				add_child(tile)
				tile.set_owner(self)
				tile.set_name(str(x+y*w))
				tile.set_texture(spritesheet)
				tile.set_region(true)
				tile.set_region_rect(Rect2(x*tileSize, y*tileSize, tileSize, tileSize))
				tile.set_pos(Vector2(x*tileSize+tileSize/2, y*tileSize+tileSize/2))

marcelofg55 | 2016-06-08 15:19

That’s a really clever idea, so now all you need is the tile size and any spritesheet just works! Thanks for sharing the change :slight_smile:

Also, a few days ago I found an actual plugin for importing tilesets from spritesheets. I haven’t used it too much just yet, but it seems nice and is much easier to use than a tool script.
Here’s a link. Just add the “Create_Tileset” folder to the “.godot/plugins” folder and start godot.

Edit: remembered to add the link!

batmanasb | 2016-06-09 01:35