Last active
April 6, 2022 00:02
-
-
Save Aldlevine/93b8958a39fe7ce7ad8c2b253ccec1c5 to your computer and use it in GitHub Desktop.
Adds an animated atlas texture to Godot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extends AtlasTexture | |
class_name AnimatedAtlasTexture | |
export(int, 1, 100) var h_frames := 1 | |
export(int, 1, 100) var v_frames := 1 | |
export var fps := 10.0 | |
var previous_frame := 0 | |
var frame := 0 | |
func _init() -> void: | |
var err = VisualServer.connect("frame_pre_draw", self, "_update") | |
assert(err == OK) | |
func _update() -> void: | |
if atlas: | |
previous_frame = frame | |
var img := atlas.get_data() | |
var size = img.get_size() | |
var frame_size = size / Vector2(h_frames, v_frames) | |
frame = int(int(OS.get_ticks_msec() / (1000.0 / fps)) % (h_frames * v_frames)) | |
var frame_pos = Vector2(frame % h_frames, floor(float(frame) / h_frames)) | |
region = Rect2(frame_size * frame_pos, frame_size) | |
if previous_frame != frame: | |
emit_changed() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Use this instead of a TileSet for any TileSet that contains AnimatedAtlasTexture. | |
## Can be added as a script to any TileSet resource, or you can create it directly in the | |
## TileMap's tile_set field by selecting "New AnimatedTileSet" instead of "New TileSet" | |
## The key is that emit_changed() must be called for the TileMap to update. | |
tool | |
extends TileSet | |
class_name AnimatedTileSet | |
var _needs_update := false | |
func _init() -> void: | |
var err | |
var tiles := get_tiles_ids() | |
for tile in tiles: | |
var tex = tile_get_texture(tile) | |
if tex is AnimatedAtlasTexture: | |
err = tex.connect("changed", self, "_set_needs_update", []) | |
assert(err == OK) | |
err = VisualServer.connect("frame_pre_draw", self, "_update", [], CONNECT_DEFERRED) | |
assert(err == OK) | |
func _set_needs_update() -> void: | |
_needs_update = true | |
func _update() -> void: | |
if _needs_update: | |
emit_changed() | |
_needs_update = false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[plugin] | |
name="animated_atlas_texture" | |
description="Adds an animated atlas texture resource" | |
author="Aaron Levine" | |
version="" | |
script="plugin.gd" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
tool | |
extends EditorPlugin | |
var resource : AnimatedAtlasTexture | |
func _enter_tree(): | |
VisualServer.connect("frame_pre_draw", self, "_update") | |
func _exit_tree(): | |
VisualServer.disconnect("frame_pre_draw", self, "_update") | |
func handles(object: Object) -> bool: | |
if object is AnimatedAtlasTexture: | |
resource = object as AnimatedAtlasTexture | |
return object is AnimatedAtlasTexture | |
func _update() -> void: | |
if resource is AnimatedAtlasTexture: | |
if resource.atlas: | |
var img := resource.atlas.get_data() | |
var size = img.get_size() | |
var frame_size = size / Vector2(resource.h_frames, resource.v_frames) | |
var frame = int(int(OS.get_ticks_msec() / (1000.0 / resource.fps)) % (resource.h_frames * resource.v_frames)) | |
var frame_pos = Vector2(frame % resource.h_frames, floor(float(frame) / resource.h_frames)) | |
resource.region = Rect2(frame_size * frame_pos, frame_size) |
Changed a lil bit, maked script straightforward + added support per AtlasTexture region (if you want make mutltiple AtlasTextures from single StreamTexture)
animated_atlas_texture.gd
class_name AnimatedAtlasTexture extends AtlasTexture
export(int, 1, 100) var h_frames := 1
export(int, 1, 100) var v_frames := 1
export var fps := 10.0
var frame_position : Vector2
var frame_size : Vector2
var frame_last := 0
var frame := 0
func init() -> void:
frame_size = region.size / Vector2(h_frames, v_frames)
frame_position = region.position
VisualServer.connect("frame_pre_draw", self, "_on_frame_pre_draw")
func _on_frame_pre_draw() -> void:
if !atlas: return
frame = int(OS.get_ticks_msec() / (1000.0 / fps)) % (h_frames * v_frames)
region = Rect2(
frame_position + (frame_size * Vector2(frame % h_frames, frame / h_frames)),
frame_size)
if frame_last != frame:
frame_last = frame
emit_changed()
tilemap.gd
extends TileMap
func _ready() -> void:
for tile in tile_set.get_tiles_ids():
var texture := tile_set.tile_get_texture(tile)
if texture is AnimatedAtlasTexture:
texture.init()
texture.connect("changed", self, "_on_AnimatedAtlasTexture_changed")
func _on_AnimatedAtlasTexture_changed() -> void:
tile_set.emit_changed()
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In my setup,
previous_frame
is reassigned in the beginning of the update function (beforeframe
gets rewritten), but your placement should work just the same.Also, I've updated the solution for TileMaps by creating a custom TileSet instead. The gist was updated to include
animated_tile_set.gd
. I believe this is a better solution.And one more thing, you can get better in editor previewing by turning on "Editor Settings -> Interface -> Editor -> Update Continuously", but obviously this will make the editor more resource intensive.