Skip to content

Instantly share code, notes, and snippets.

@ChillMagic
Last active March 23, 2026 02:16
Show Gist options
  • Select an option

  • Save ChillMagic/6708d541a5146945b22aa5f39e6edb22 to your computer and use it in GitHub Desktop.

Select an option

Save ChillMagic/6708d541a5146945b22aa5f39e6edb22 to your computer and use it in GitHub Desktop.
Convert RPG Maker 2000/2003 Chipset to Godot 4 Tileset
@tool
extends EditorScript
class Rect2iIterator:
var _begin: Vector2i
var _current: Vector2i
var _rect: Rect2i
static func from_vector2(vector2: Vector2i) -> Rect2iIterator:
return Rect2iIterator.new(Rect2i(Vector2i(0, 0), vector2))
func _init(rect: Rect2i):
self._begin = rect.position
self._current = self._begin
self._rect = rect
func _iter_init(_arg):
self._current = self._begin
return self._rect.size.x > 0 and self._rect.size.y > 0
func _iter_next(_arg):
self._current.x += 1
if self._current.x >= self._rect.position.x + self._rect.size.x:
self._current.x = self._rect.position.x
self._current.y += 1
if self._current.y >= self._rect.position.y + self._rect.size.y:
return false
return true
func _iter_get(_arg):
return self._current
class ImageSpan:
var data: Object
var rect: Rect2i
func _init(p_data: Object, p_rect: Rect2i):
self.data = p_data
self.rect = p_rect
assert(ImageSpan._check_size(p_data.get_size(), p_rect))
static func from_image(image: Image) -> ImageSpan:
return ImageSpan.new(image, Rect2i(Vector2i(0, 0), image.get_size()))
static func _check_size(old_size: Vector2i, new_rect: Rect2i) -> bool:
var new_size = new_rect.size
if not (new_size.x > 0 and new_size.y > 0) or\
not (new_size.x + new_rect.position.x <= old_size.x and new_size.y + new_rect.position.y <= old_size.y):
push_error("Invalid rect: %s, the original size: %s" % [new_rect, old_size])
return false
return true
func get_base_image() -> Image:
if self.data.is_class("Image"):
return self.data
else:
return self.data.get_base_image()
func get_base_position() -> Vector2i:
return ImageSpan._get_base_position(self.data, self.rect.position)
static func _get_base_position(curr_data: Object, curr_pos: Vector2i) -> Vector2i:
if curr_data.is_class("Image"):
return curr_pos
else:
return _get_base_position(curr_data.data, curr_pos + curr_data.rect.position)
func get_size() -> Vector2i:
return self.rect.size
func get_format() -> int:
return self.get_base_image().get_format()
func blit_rect(src: ImageSpan, src_rect: Rect2i, dst: Vector2i):
assert(ImageSpan._check_size(self.get_size(), Rect2i(dst, src_rect.size)))
self.get_base_image().blit_rect(src.get_base_image(), Rect2i(src.get_base_position() + src_rect.position, src_rect.size), self.get_base_position() + dst)
func to_image() -> Image:
var result = Image.create(self.get_size().x, self.get_size().y, false, self.get_base_image().get_format())
ImageSpan.from_image(result).blit_rect(self, Rect2i(Vector2i(0, 0), self.get_size()), Vector2i(0, 0))
return result
enum TilesetViewUnitKind { Image, ImageSpan, TilesetView }
class TilesetViewUnit:
var kind: TilesetViewUnitKind
func _init(p_kind: TilesetViewUnitKind):
self.kind = p_kind
class ImageTilesetViewUnit extends TilesetViewUnit:
var data: Image
var rect: Rect2i
func _init(p_data: Image, p_rect: Rect2i):
super(TilesetViewUnitKind.Image)
self.data = p_data
self.rect = p_rect
class ImageSpanTilesetViewUnit extends TilesetViewUnit:
var data: ImageSpan
var rect: Rect2i
func _init(p_data: ImageSpan, p_rect: Rect2i):
super(TilesetViewUnitKind.ImageSpan)
self.data = p_data
self.rect = p_rect
class TilesetViewTilesetViewUnit extends TilesetViewUnit:
var data: TilesetView
var rect: Rect2i
func _init(p_data: TilesetView, p_rect: Rect2i):
super(TilesetViewUnitKind.TilesetView)
self.data = p_data
self.rect = p_rect
class TilesetView:
var image_format: int
var size: Vector2i
var tile_size: Vector2i
var _data: Array[TilesetViewUnit]
func _init(p_image_format: int, p_size: Vector2i, p_tile_size: Vector2i):
self.image_format = p_image_format
self.size = p_size
self.tile_size = p_tile_size
self._data = []
self._data.resize(self.size.x * self.size.y)
func _get_index(pos: Vector2i) -> int:
if pos.x < self.size.x and pos.y < self.size.y and pos.x >= 0 and pos.y >= 0:
return pos.y * self.size.x + pos.x
else:
push_error("Invalid position: %s" % pos)
return 0
func get_tile_data(pos: Vector2i) -> TilesetViewUnit:
return self._data[_get_index(pos)]
func set_tile_data(pos: Vector2i, src: TilesetViewUnit):
self._data[_get_index(pos)] = src
func set_image_unit_tile_data(pos: Vector2i, image: Image, src: Vector2i):
self._data[_get_index(pos)] = ImageTilesetViewUnit.new(image, Rect2i(src, Vector2i(1, 1)))
func set_imagespan_unit_tile_data(pos: Vector2i, image_span: ImageSpan, src: Vector2i):
self._data[_get_index(pos)] = ImageSpanTilesetViewUnit.new(image_span, Rect2i(src, Vector2i(1, 1)))
func set_image_unit_tile_data_from_list(image: Image, src_list: Array):
assert(self._data.size() == src_list.size())
for i in range(self._data.size()):
var src = src_list[i]
if typeof(src) == TYPE_VECTOR2I:
self._data[i] = ImageTilesetViewUnit.new(image, Rect2i(src, Vector2i(1, 1)))
else:
self._data[i] = ImageTilesetViewUnit.new(image, Rect2i(Vector2i(src[0], src[1]), Vector2i(1, 1)))
func set_imagespan_unit_tile_data_from_list(image_span: ImageSpan, src_list: Array):
assert(self._data.size() == src_list.size())
for i in range(self._data.size()):
var src = src_list[i]
if typeof(src) == TYPE_VECTOR2I:
self._data[i] = ImageSpanTilesetViewUnit.new(image_span, Rect2i(src, Vector2i(1, 1)))
else:
self._data[i] = ImageSpanTilesetViewUnit.new(image_span, Rect2i(Vector2i(src[0], src[1]), Vector2i(1, 1)))
func set_tilesetview_tile_data(pos: Vector2i, tilesetview: TilesetView):
self.set_tile_data(pos, TilesetViewTilesetViewUnit.new(tilesetview, Rect2i(Vector2i(), tilesetview.size)))
func assemble_tileset_image() -> Image:
var image_size = self.size * self.tile_size
var result = Image.create(image_size.x, image_size.y, false, self.image_format)
for pos in Rect2iIterator.from_vector2(self.size):
var v = self.get_tile_data(pos)
if v:
match v.kind:
TilesetViewUnitKind.Image:
result.blit_rect(v.data, Rect2i(v.rect.position * self.tile_size, v.rect.size * self.tile_size), pos * self.tile_size)
TilesetViewUnitKind.ImageSpan:
ImageSpan.from_image(result).blit_rect(v.data, Rect2i(v.rect.position * self.tile_size, v.rect.size * self.tile_size), pos * self.tile_size)
TilesetViewUnitKind.TilesetView:
var image = v.data.assemble_tileset_image()
result.blit_rect(image, Rect2i(v.rect.position * self.tile_size, v.rect.size * self.tile_size), pos * self.tile_size)
return result
func __is_palettle_format(file: FileAccess) -> bool:
if file.get_length() < 43: # PNG signature + ... + PLTE + first palettle
return false
var file_position = file.get_position()
# 137 80 78 71 13 10 26 10
file.seek(0)
for v in [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]:
if file.get_8() != v:
file.seek(file_position)
return false
# P Mode, 8 bits
file.seek(0x18)
for v in [0x08, 0x03]:
if file.get_8() != v:
file.seek(file_position)
return false
file.seek(file_position)
return true
func __get_first_palette_colour(file: FileAccess) -> Color:
assert(__is_palettle_format(file))
# First colour
var file_position = file.get_position()
file.seek_end()
var file_size = file.get_position()
file.seek(0x21)
while file.get_position() < file_size:
var buffer = []
for _i in range(4):
buffer.append(file.get_8())
var length = buffer[0] * 0x1000 + buffer[1] * 0x0100 + buffer[2] * 0x0010 + buffer[3] * 0x0001
buffer = []
for _i in range(4):
buffer.append(file.get_8())
var chunk_kind = "".join(buffer.map(func(c): return String.chr(c)))
if chunk_kind == "PLTE":
var r = file.get_8()
var g = file.get_8()
var b = file.get_8()
file.seek(file_position)
return Color("#%02x%02x%02x" % [r, g, b])
else:
file.seek(file.get_position() + length + 4)
file.seek(file_position)
push_error("Can not find first palette colour.")
return Color()
func __make_color_transparent(image: Image, transparent_colour: Color):
for x in range(image.get_width()):
for y in range(image.get_height()):
if image.get_pixel(x, y) == transparent_colour:
image.set_pixel(x, y, Color(0, 0, 0, 0))
func load_may_transparent_image(path: String) -> Image:
var file = FileAccess.open(path, FileAccess.READ)
if file and file.is_open():
if __is_palettle_format(file):
var transparent_colour: Color = __get_first_palette_colour(file)
var image: Image = Image.load_from_file(path)
image.convert(Image.FORMAT_RGBA8)
__make_color_transparent(image, transparent_colour)
return image
else:
return Image.load_from_file(path)
else:
return null
func __get_tile_rect(position: Vector2i, tile_size: Vector2i) -> Rect2i:
return Rect2i(position.x * tile_size.x, position.y * tile_size.y, tile_size.x, tile_size.y)
func __check_tile_size(image: Image, tile_size: Vector2i, size: Vector2i) -> bool:
return image.get_size() == size * tile_size
func reorganize_autotiles_from_3x4_to_2x3(image: Image, tile_size: Vector2i) -> Image:
assert(__check_tile_size(image, tile_size, Vector2i(3, 4)))
var positions = [[0, 0], [0, 2], [1, 0], [1, 2], [3, 0], [3, 2]]
var new_image = Image.create(2 * tile_size.x, 3 * tile_size.y, false, image.get_format())
var index = 0
for row in range(3):
for col in range(2):
var position = Vector2i(positions[index][1], positions[index][0])
var rect = __get_tile_rect(position, tile_size)
new_image.blit_rect(image, rect, Vector2i(col, row) * tile_size)
index += 1
return new_image
func reorganize_autotiles_from_3x4_to_2x3_span(image_span: ImageSpan, tile_size: Vector2i) -> Image:
assert(image_span.get_size() == tile_size * Vector2i(3, 4))
var tileset = TilesetView.new(image_span.get_format(), Vector2i(2, 3), tile_size)
tileset.set_imagespan_unit_tile_data_from_list(image_span, [[0, 0], [2, 0], [0, 1], [2, 1], [0, 3], [2, 3]])
return tileset.assemble_tileset_image()
func get_godot_autotiles_size() -> Vector2i:
return Vector2i(12, 4)
func __init_autotiles_data():
const I1 = [2, 0]; const I2 = [3, 0]; const I3 = [2, 1]; const I4 = [3, 1] # Inner corner
const O1 = [0, 0]; const O2 = [1, 0]; const O3 = [0, 1]; const O4 = [1, 1] # Outer corner
const TL = [0, 2]; const TR = [3, 2]; const BL = [0, 5]; const BR = [3, 5] # Corners
const T1 = [1, 2]; const T2 = [2, 2]; const L1 = [0, 3]; const L2 = [0, 4] # Edge part
const R1 = [3, 3]; const R2 = [3, 4]; const B1 = [1, 5]; const B2 = [2, 5] # Edge part
const N1 = [1, 3]; const N2 = [2, 3]; const N3 = [1, 4]; const N4 = [2, 4] # Normal path
return [
TL,TR, TL,T1,T2,T1,T2,TR, N4,I2,T2,T1,T2,T1,I1,N3, TL,T1,I1,I2,T2,T1,T2,TR,
L1,R1, L1,I4,I3,I4,I3,R1, I3,I4,I3,N1,N2,I4,I3,I4, L1,N1,N2,N1,N2,N1,N2,R1,
L2,R2, L2,I2,I1,I2,I1,R2, L2,I2,I1,N3,N4,I2,I1,R2, L2,N3,I1,N3,O1,O2,N4,I2,
L1,R1, L1,I4,I3,I4,I3,R1, L1,N1,N2,N1,N2,N1,N2,R1, L1,N1,N2,I4,O3,O4,N2,I4,
L2,R2, L2,I2,I1,I2,I1,R2, L2,N3,N4,N3,N4,N3,N4,R2, I1,N3,N4,N3,N4,I2,N4,R2,
BL,BR, BL,B1,B2,B1,B2,BR, L1,I4,I3,N1,N2,I4,I3,R1, I3,N1,N2,N1,I3,N1,N2,R1,
TL,TR, TL,T1,T2,T1,T2,TR, I1,I2,I1,N3,N4,I2,I1,I2, L2,N3,N4,N3,N4,N3,N4,R2,
BL,BR, BL,B1,B2,B1,B2,BR, N2,I4,B2,B1,B2,B1,I3,N1, BL,B1,B2,B1,I3,I4,B2,BR,
]
var AutotilesData = __init_autotiles_data()
func create_godot_autotiles_from_2x3_span(image_span: ImageSpan, tile_size: Vector2i) -> Image:
assert(image_span.get_size() == tile_size * Vector2i(2, 3))
var tileset = TilesetView.new(image_span.get_format(), get_godot_autotiles_size() * 2, tile_size / 2)
tileset.set_imagespan_unit_tile_data_from_list(image_span, AutotilesData)
return tileset.assemble_tileset_image()
func create_godot_autotiles_from_3x4_span(image_span: ImageSpan, tile_size: Vector2i) -> Image:
var new_image = reorganize_autotiles_from_3x4_to_2x3_span(image_span, tile_size)
return create_godot_autotiles_from_2x3_span(ImageSpan.from_image(new_image), tile_size)
func create_godot_autotiles(image_span: ImageSpan, tile_size: Vector2i, size: Vector2i) -> Image:
if size == Vector2i(2, 3):
return create_godot_autotiles_from_2x3_span(image_span, tile_size)
elif size == Vector2i(3, 4):
return create_godot_autotiles_from_3x4_span(image_span, tile_size)
assert(false)
return null
func __get_average_colour(image: Image, region: Rect2i) -> Color:
var colour_count = 0
var colour_sum = Color(0, 0, 0, 0)
for position in Rect2iIterator.new(region):
var colour = image.get_pixel(position.x, position.y)
if colour.a > 0:
colour_sum += colour
colour_count += 1
var result = colour_sum / colour_count
result.a = 1
return result
const TerrainDirectionMap = {
1: TileSet.CELL_NEIGHBOR_TOP_LEFT_CORNER,
2: TileSet.CELL_NEIGHBOR_TOP_SIDE,
3: TileSet.CELL_NEIGHBOR_TOP_RIGHT_CORNER,
4: TileSet.CELL_NEIGHBOR_LEFT_SIDE,
5: TileSet.CELL_NEIGHBOR_RIGHT_SIDE,
6: TileSet.CELL_NEIGHBOR_BOTTOM_LEFT_CORNER,
7: TileSet.CELL_NEIGHBOR_BOTTOM_SIDE,
8: TileSet.CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER,
}
const TerrainDirectionData = [
[0x40,0x50,0x58,0x48, 0x5b,0xd8,0x78,0x5e, 0xd0,0xfa,0xf8,0x68],
[0x42,0x52,0x5a,0x4a, 0xd2,0xfe,0xfb,0x6a, 0xd6,0x7e,null,0x7b],
[0x02,0x12,0x1a,0x0a, 0x56,0xdf,0x7f,0x4b, 0xde,0xff,0xdb,0x6b],
[0x00,0x10,0x18,0x08, 0x7a,0x1e,0x1b,0xda, 0x16,0x1f,0x5f,0x0b],
]
func create_tileset_source(tileset: TileSet, image: Image, tile_size: Vector2i):
var tileset_source = TileSetAtlasSource.new()
tileset_source.texture = ImageTexture.create_from_image(image)
tileset_source.texture_region_size = tile_size
tileset.add_source(tileset_source)
return tileset_source
func add_terrain_set(tileset: TileSet) -> int:
tileset.add_terrain_set()
var terrain_set = tileset.get_terrain_sets_count() - 1
tileset.set_terrain_set_mode(terrain_set, TileSet.TERRAIN_MODE_MATCH_CORNERS_AND_SIDES)
return terrain_set
func set_terrain(tileset_source: TileSetAtlasSource, tileset: TileSet, terrain_set: int, terrain_name: String, tile_size: Vector2i, start_position: Vector2i, frames_count: int = 0):
tileset.add_terrain(terrain_set)
var terrain_index = tileset.get_terrains_count(terrain_set) - 1
var size = Vector2i(TerrainDirectionData[0].size(), TerrainDirectionData.size())
var average_colour = __get_average_colour(tileset_source.texture.get_image(),
Rect2i(start_position * tile_size, size * tile_size))
tileset.set_terrain_color(terrain_set, terrain_index, average_colour.inverted())
tileset.set_terrain_name(terrain_set, terrain_index, terrain_name)
for position in Rect2iIterator.new(Rect2i(start_position, size)):
tileset_source.create_tile(position)
if frames_count:
tileset_source.set_tile_animation_columns(position, 1)
tileset_source.set_tile_animation_separation(position, Vector2i(0, 3))
tileset_source.set_tile_animation_frames_count(position, frames_count)
tileset_source.set_tile_animation_speed(position, 2)
var tile_data = tileset_source.get_tile_data(position, 0)
var _direction = TerrainDirectionData[position.y % size.y][position.x % size.x]
if _direction != null:
tile_data.terrain_set = terrain_set
tile_data.terrain = terrain_index
for i in range(9):
if _direction & (0x1 << i):
tile_data.set_terrain_peering_bit(TerrainDirectionMap[i+1], terrain_index)
func create_godot_autotiles_animation(image: Image, config: TilesetSlice) -> Image:
var tile_size = config.tile_size
var size = config.size
var new_total_image = Image.create(12 * tile_size.x, 4 * config.frames_count * tile_size.y, false, image.get_format())
var i = 0
for r in Rect2iIterator.new(Rect2i(Vector2i(0, 0), Vector2i(4, 1))):
var image_position = r * tile_size * size
var image_size = size * tile_size
var new_image = Image.create(image_size.x, image_size.y, false, image.get_format())
new_image.blit_rect(image, Rect2i(image_position, image_size), Vector2i(0, 0))
new_image = create_godot_autotiles(ImageSpan.from_image(new_image), tile_size, size)
new_total_image.blit_rect(new_image, Rect2i(Vector2i(0, 0), get_godot_autotiles_size() * tile_size), Vector2i(0, i) * get_godot_autotiles_size() * tile_size)
i += 1
return new_total_image
class TilesetSlice:
var size: Vector2i
var tile_size: Vector2i
var frames_count: int
func _init(p_size: Vector2i, p_tile_size: Vector2i, p_frames_count: int):
self.size = p_size
self.tile_size = p_tile_size
self.frames_count = p_frames_count
func __create_rpgmaker_2000_2003_sea_autotiles(span_a: ImageSpan, span_b: ImageSpan, image_format: int, pos_map: Array, tile_size: Vector2i) -> Image:
var tileset = TilesetView.new(image_format, Vector2i(4, 6), tile_size / 2)
for pos in Rect2iIterator.from_vector2(Vector2i(4, 6)):
var dat = pos_map[pos.y][pos.x]
var span = span_a if (dat & 0x10) == 0 else span_b
var src_pos = Vector2i((dat & 0xf) % 2, (dat & 0xf) / 2)
tileset.set_imagespan_unit_tile_data(pos, span, src_pos)
var tileset_image_2x3 = tileset.assemble_tileset_image()
var tileset_image = create_godot_autotiles(ImageSpan.from_image(tileset_image_2x3), tile_size, Vector2i(2, 3))
return tileset_image
func create_rpgmaker_2000_2003_tileset(file_path: String) -> TileSet:
var image = load_may_transparent_image(file_path)
var tile_size = Vector2i(16, 16)
var tileset = TileSet.new()
tileset.tile_size = tile_size
var terrain_set = add_terrain_set(tileset)
# Block A B
var a1_index = [[0, 0], [1, 0], [2, 0]]
var a2_index = [[3, 0], [4, 0], [5, 0]]
var b_index = [[0, 1], [1, 1], [2, 1]]
var to_span = func(pos): return ImageSpan.new(image, Rect2i(Vector2i(pos[0], pos[1]) * Vector2i(1, 4) * tile_size, Vector2i(1, 4) * tile_size))
var a1_span = a1_index.map(to_span)
var a2_span = a2_index.map(to_span)
var b_span = b_index.map(to_span)
const data_ab_1 = [
[0x00, 0x01, 0x0c, 0x0d],
[0x02, 0x03, 0x0e, 0x0f],
[0x00, 0x09, 0x08, 0x01],
[0x06, 0x13, 0x12, 0x07],
[0x04, 0x11, 0x10, 0x05],
[0x02, 0x0b, 0x0a, 0x03],
]
const data_ab_2 = [
[0x00, 0x01, 0x0c, 0x0d],
[0x02, 0x03, 0x0e, 0x0f],
[0x00, 0x09, 0x08, 0x01],
[0x06, 0x1f, 0x1e, 0x07],
[0x04, 0x1d, 0x1c, 0x05],
[0x02, 0x0b, 0x0a, 0x03],
]
const data_b_1 = [
[0x18, 0x19, 0x1c, 0x1d],
[0x1a, 0x1b, 0x1e, 0x1f],
[0x18, 0x1d, 0x1c, 0x19],
[0x1e, 0x1f, 0x1e, 0x1f],
[0x1c, 0x1d, 0x1c, 0x1d],
[0x1a, 0x1f, 0x1e, 0x1b],
]
const data_b_2 = [
[0x14, 0x15, 0x10, 0x11],
[0x16, 0x17, 0x12, 0x13],
[0x14, 0x11, 0x10, 0x15],
[0x12, 0x13, 0x12, 0x13],
[0x10, 0x11, 0x10, 0x11],
[0x16, 0x13, 0x12, 0x17],
]
var data = [
[[data_ab_1, a1_span[0], b_span[0]], [data_ab_1, a2_span[0], b_span[0]], [data_b_1, null, b_span[0]]],
[[data_ab_1, a1_span[1], b_span[1]], [data_ab_1, a2_span[1], b_span[1]], [data_b_1, null, b_span[1]]],
[[data_ab_1, a1_span[2], b_span[2]], [data_ab_1, a2_span[2], b_span[2]], [data_b_1, null, b_span[2]]],
[[data_ab_2, a1_span[0], b_span[0]], [data_ab_2, a2_span[0], b_span[0]], [data_b_2, null, b_span[0]]],
[[data_ab_2, a1_span[1], b_span[1]], [data_ab_2, a2_span[1], b_span[1]], [data_b_2, null, b_span[1]]],
[[data_ab_2, a1_span[2], b_span[2]], [data_ab_2, a2_span[2], b_span[2]], [data_b_2, null, b_span[2]]],
]
var tileset_block_ab = TilesetView.new(image.get_format(), Vector2i(3, 6), get_godot_autotiles_size() * tile_size)
for pos in Rect2iIterator.from_vector2(Vector2i(3, 6)):
var value = data[pos.y][pos.x]
var tileset_image = __create_rpgmaker_2000_2003_sea_autotiles(value[1], value[2], image.get_format(), value[0], tile_size)
tileset_block_ab.set_image_unit_tile_data(pos, tileset_image, Vector2i(0, 0))
var tileset_source_block_ab = create_tileset_source(tileset, tileset_block_ab.assemble_tileset_image(), tile_size)
var terrain_name_map = [
["A1_shallow", "A2_shallow", "B_shallow"],
["A1_deep", "A2_deep", "B_deep"],
]
for pos in Rect2iIterator.from_vector2(Vector2i(3, 2)):
var terrain_name = "autotile_%s" % terrain_name_map[pos.y][pos.x]
set_terrain(tileset_source_block_ab, tileset, terrain_set, terrain_name, tile_size, pos * Vector2i(1, 3) * get_godot_autotiles_size(), 3)
# Block D
var tileset_block_d = TilesetView.new(image.get_format(), Vector2i(1, 3), tile_size * Vector2i(6, 8))
tileset_block_d.set_image_unit_tile_data_from_list(image, [[0, 1], [1, 0], [1, 1]])
var tileset_block_d_image = tileset_block_d.assemble_tileset_image()
var tileset_block_d_autotile = TilesetView.new(image.get_format(), Vector2i(2, 6), tile_size * get_godot_autotiles_size())
for pos in Rect2iIterator.new(Rect2i(Vector2i(0, 0), Vector2i(2, 6))):
var image_span_unit = ImageSpan.new(tileset_block_d_image, Rect2i(pos * Vector2i(3, 4) * tile_size, Vector2i(3, 4) * tile_size))
var image_unit = create_godot_autotiles_from_3x4_span(image_span_unit, tile_size)
tileset_block_d_autotile.set_image_unit_tile_data(pos, image_unit, Vector2i(0, 0))
var tileset_source_block_d = create_tileset_source(tileset, tileset_block_d_autotile.assemble_tileset_image(), tile_size)
for pos in Rect2iIterator.from_vector2(Vector2i(2, 6)):
var terrain_name = "autotile_D%s" % (pos.y * 2 + pos.x + 1)
set_terrain(tileset_source_block_d, tileset, terrain_set, terrain_name, tile_size, pos * get_godot_autotiles_size())
# Block C
var tileset_block_c = TilesetView.new(image.get_format(), Vector2i(1, 1), tile_size * Vector2i(3, 4))
tileset_block_c.set_image_unit_tile_data_from_list(image, [[1, 1]])
var tileset_source_block_c = create_tileset_source(tileset, tileset_block_c.assemble_tileset_image(), tile_size)
for position in Rect2iIterator.from_vector2(Vector2i(3, 1)):
tileset_source_block_c.create_tile(position)
tileset_source_block_c.set_tile_animation_columns(position, 1)
tileset_source_block_c.set_tile_animation_separation(position, Vector2i(0, 0))
tileset_source_block_c.set_tile_animation_frames_count(position, 4)
tileset_source_block_c.set_tile_animation_speed(position, 4)
# Block E F
var tileset_block_ef = TilesetView.new(image.get_format(), Vector2i(2, 3), tile_size * Vector2i(6, 8))
tileset_block_ef.set_image_unit_tile_data_from_list(image, [[2, 0], [3, 1], [2, 1], [4, 0], [3, 0], [4, 1]])
var tileset_source_block_ef = create_tileset_source(tileset, tileset_block_ef.assemble_tileset_image(), tile_size)
for position in Rect2iIterator.new(Rect2i(Vector2i(0, 0), Vector2i(12, 24))):
tileset_source_block_ef.create_tile(position)
return tileset
func convert_rpgmaker_2000_2003_tilesets(input_dir: String, output_dir: String):
for filename in DirAccess.get_files_at(input_dir):
if filename.to_lower().ends_with(".png"):
var file = input_dir.path_join(filename)
var tileset = create_rpgmaker_2000_2003_tileset(file)
ResourceSaver.save(tileset, output_dir.path_join("%s.tres" % filename.substr(0, filename.length() - 4)))
func _run():
var input_dir = "res://input/"
var output_dir = "res://output/"
for f in DirAccess.get_files_at(output_dir):
DirAccess.remove_absolute(output_dir.path_join(f))
DirAccess.remove_absolute(output_dir)
DirAccess.remove_absolute(output_dir)
DirAccess.make_dir_recursive_absolute(output_dir)
convert_rpgmaker_2000_2003_tilesets(input_dir, output_dir)
EditorInterface.get_resource_filesystem().scan()
await EditorInterface.get_resource_filesystem().filesystem_changed
return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment