115 lines
4.3 KiB
GDScript
115 lines
4.3 KiB
GDScript
class_name SpritesheetParser
|
|
|
|
var spritesheet
|
|
var max_dimensions : Vector2i
|
|
|
|
var _parser = XMLParser.new()
|
|
var _filename_regex = RegEx.new()
|
|
|
|
func parse_spritesheet(path):
|
|
var animations = {}
|
|
max_dimensions = Vector2i(0, 0)
|
|
_parser.open(path)
|
|
_filename_regex.compile("^(.+?)(\\d{1,4})$")
|
|
while _parser.read() != ERR_FILE_EOF:
|
|
if _parser.get_node_type() != XMLParser.NODE_ELEMENT:
|
|
continue
|
|
|
|
var node_name = _parser.get_node_name()
|
|
if node_name != "SubTexture":
|
|
continue
|
|
|
|
var frame_search = _filename_regex.search(_parser.get_named_attribute_value_safe("name"))
|
|
var frame_name = frame_search.get_string(1)
|
|
var frame_no = frame_search.get_string(2).to_int()
|
|
var frame_x = _parser.get_named_attribute_value_safe("x")
|
|
var frame_y = _parser.get_named_attribute_value_safe("y")
|
|
var frame_width = _parser.get_named_attribute_value_safe("width")
|
|
var frame_height = _parser.get_named_attribute_value_safe("height")
|
|
var frame_frame_x = _parser.get_named_attribute_value_safe("frameX")
|
|
var frame_frame_y = _parser.get_named_attribute_value_safe("frameY")
|
|
var frame_frame_width = _parser.get_named_attribute_value_safe("frameWidth")
|
|
var frame_frame_height = _parser.get_named_attribute_value_safe("frameHeight")
|
|
|
|
if not animations.has(frame_name):
|
|
animations[frame_name] = []
|
|
|
|
var array = animations[frame_name]
|
|
var frame_data = {}
|
|
|
|
if frame_x.is_valid_int() and frame_y.is_valid_int():
|
|
frame_data.pos = Vector2i(frame_x.to_int(), frame_y.to_int())
|
|
else:
|
|
frame_data.pos = Vector2i.ZERO
|
|
if frame_width.is_valid_int() and frame_height.is_valid_int():
|
|
frame_data.size = Vector2i(frame_width.to_int(), frame_height.to_int())
|
|
if frame_width.to_int() > max_dimensions.x:
|
|
max_dimensions.x = frame_width.to_int()
|
|
if frame_height.to_int() > max_dimensions.y:
|
|
max_dimensions.y = frame_height.to_int()
|
|
else:
|
|
frame_data.size = Vector2i.ZERO
|
|
if frame_frame_x.is_valid_int() and frame_frame_y.is_valid_int():
|
|
frame_data.frame_pos = Vector2i(frame_frame_x.to_int(), frame_frame_y.to_int())
|
|
else:
|
|
frame_data.frame_pos = Vector2i.ZERO
|
|
if frame_frame_width.is_valid_int() and frame_frame_height.is_valid_int():
|
|
frame_data.frame_size = Vector2i(frame_frame_width.to_int(), frame_frame_height.to_int())
|
|
if frame_frame_width.to_int() > max_dimensions.x:
|
|
max_dimensions.x = frame_frame_width.to_int()
|
|
if frame_frame_height.to_int() > max_dimensions.y:
|
|
max_dimensions.y = frame_frame_height.to_int()
|
|
else:
|
|
frame_data.frame_size = frame_data.size
|
|
|
|
if frame_no >= array.size():
|
|
array.resize(frame_no + 1)
|
|
|
|
array[frame_no] = frame_data
|
|
|
|
for animation in animations:
|
|
var anim_frames: Array = animations[animation]
|
|
while anim_frames.has(null):
|
|
anim_frames.erase(null)
|
|
|
|
spritesheet = animations
|
|
|
|
func get_props_of_animation_frame(anim:String, frameno:int):
|
|
var anim_frames = spritesheet[anim]
|
|
frameno = clamp(frameno, 0, anim_frames.size() - 1)
|
|
var frame = anim_frames[frameno]
|
|
return {
|
|
region = Rect2(frame.pos, frame.size),
|
|
margin = Rect2(-frame.frame_pos, frame.frame_size - frame.size)
|
|
}
|
|
|
|
static func load_image(path: String) -> Image:
|
|
if path.begins_with('res'):
|
|
return load(path)
|
|
else:
|
|
var file = FileAccess.open(path, FileAccess.READ)
|
|
if FileAccess.get_open_error() != OK:
|
|
print(str("Could not load image at: ",path))
|
|
return
|
|
var buffer = file.get_buffer(file.get_length())
|
|
var image:Image = Image.new()
|
|
var error = image.load_png_from_buffer(buffer)
|
|
if error != OK:
|
|
print(str("Could not load image at: ",path," with error: ",error))
|
|
return
|
|
return image
|
|
|
|
static func spritesheet_to_xml(anims:Array, size: Vector2i, imgpath: String):
|
|
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
|
xml += "<TextureAtlas imagePath=\"%s\">\n" % imgpath
|
|
for animation in anims:
|
|
var animation_stack = ""
|
|
for frame in animation.frames.size():
|
|
var cur_frame = animation.frames[frame]
|
|
if cur_frame == null: continue
|
|
var frame_id = animation.name + str(frame).pad_zeros(4)
|
|
animation_stack += "\t<SubTexture name=\"%s\" x=\"%s\" y=\"%s\" width=\"%s\" height=\"%s\" frameX=\"%s\" frameY=\"%s\" frameWidth=\"%s\" frameHeight=\"%s\" />\n" % \
|
|
[ frame_id, cur_frame.pos.x, cur_frame.pos.y, cur_frame.size.x, cur_frame.size.y, -cur_frame.frame_pos.x, -cur_frame.frame_pos.y, size.x, size.y ]
|
|
xml += animation_stack
|
|
xml += "</TextureAtlas>"
|
|
return xml
|