remove unused plugin

This commit is contained in:
Lucas 2024-07-22 23:09:53 +02:00
parent edd6ed0f4c
commit 47a983c085
13 changed files with 0 additions and 709 deletions

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 kyboon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,49 +0,0 @@
# ModularSpriteAnimationFactory
![NeonCatIcon](https://github.com/kyboon/ModularSpriteAnimationFactory/blob/master/addons/modular_sprite_animation_factory/msaf_logo.png)
A Godot 4 plugin to generate animations for modular 2d sprites. Generated animations will have multiple tracks, one for each Sprite2D node.
## Installation
1. Download the plugin from github and place the `addons` directory to your Godot project root folder. Alternatively, you can install it from the `AssetLib` in the Godot editor.
2. In the Godot editor, go to `Project` > `Project Settings` > `Plugins` and enable `Modular Sprite Animation Factory`.
## Usage
1. Prepare your sprites. Split it to different parts and convert them to white (or greyscale). Example below:
Original:
![Original](https://github.com/kyboon/ModularSpriteAnimationFactory/blob/master/example/assets/character_base_16x16.png)
Head:
![Head](https://github.com/kyboon/ModularSpriteAnimationFactory/blob/master/example/assets/character_base_head.png)
Body:
![Head](https://github.com/kyboon/ModularSpriteAnimationFactory/blob/master/example/assets/character_base_body.png)
Eyes:
![Head](https://github.com/kyboon/ModularSpriteAnimationFactory/blob/master/example/assets/character_base_eyes.png)
Outline:
![Head](https://github.com/kyboon/ModularSpriteAnimationFactory/blob/master/example/assets/character_base_outlines.png)
2. Setup your nodes, it has to be a `Node2D`, **contains an `AnimationPlayer` and at least a `Sprite2D`** among its children. It's recommended to name the `Sprite2D`s accordingly. Example below:
- `Node2D`
- `AnimationPlayer`
- `Sprite2D`
- `Sprite2D`
- ... more `Sprite2D`s
![image](https://github.com/kyboon/ModularSpriteAnimationFactory/assets/24255335/c5050f25-0de4-4c87-ba66-6975068d67ed)
3. Set the textures of the `Sprite2D`s with your sprites. And set the Hframes and Vframes (under the `Sprite2D > Animation` section), in the example it's a 4x4 spritesheet.
![image](https://github.com/kyboon/ModularSpriteAnimationFactory/assets/24255335/03a9659c-f43c-424b-a997-981b6bbd1a71)
4. You can now customize your character by setting different colors to each part of the sprite. To do so, in the `CanvasItem > Visibility` section, change the modulate color. You can also change that via a script. Alternatively, you can also customize your character by changing the texture. For example, you can have a `Sprite2D` node named `Hat`, and you can change the character's hat to different styles, instead of just changing the hat color.
![image](https://github.com/kyboon/ModularSpriteAnimationFactory/assets/24255335/2ad46b56-953e-4cd3-8344-af3e188a8624)
![image](https://github.com/kyboon/ModularSpriteAnimationFactory/assets/24255335/ff7a6a07-c91e-47ef-a7eb-7ee72fcfc041)
5. When you select the root Node2D, a tab will apear on the right panel, named `MSAF`. You can then manage and generate animations using it.
![image](https://github.com/kyboon/ModularSpriteAnimationFactory/assets/24255335/534c81bf-99f8-450d-8a85-a35ffd3902e2)
6. The result of the generated animation:
![image](https://github.com/kyboon/ModularSpriteAnimationFactory/assets/24255335/d2c96a0b-db67-4e16-ade0-01085408a640)

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://rwsj5eomxtuy"
path="res://.godot/imported/checkbox-blank-circle.png-19ed1aa8d0ec722460ac308e98c5b30f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/modular_sprite_animation_factory/assets/checkbox-blank-circle.png"
dest_files=["res://.godot/imported/checkbox-blank-circle.png-19ed1aa8d0ec722460ac308e98c5b30f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ckdctfvm4f0t2"
path="res://.godot/imported/checkbox-circle.png-3e5f3f4552812201969d5bcd3ec00ca7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/modular_sprite_animation_factory/assets/checkbox-circle.png"
dest_files=["res://.godot/imported/checkbox-circle.png-3e5f3f4552812201969d5bcd3ec00ca7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -1,246 +0,0 @@
@tool
extends Control
var sprite_node_names
var selected_sprite_nodes: Array[bool] = []
var selected_library = ""
var lib_names: Array[StringName] = []
var animation_parts: Array[MSAFPart] = []
var checked_tex = preload("res://addons/modular_sprite_animation_factory/assets/checkbox-circle.png")
var unchecked_tex = preload("res://addons/modular_sprite_animation_factory/assets/checkbox-blank-circle.png")
var anim_player: AnimationPlayer
func setup_dock(node_names, animation_player):
anim_player = animation_player
sprite_node_names = node_names
refresh_all()
func refresh_all():
update_library_list()
update_sprite_node_list()
update_visible_anim()
update_animation_list()
%ChangeNotAppliedLabel.visible = false
func update_sprite_node_list():
%SpriteNodeItemList.clear()
selected_sprite_nodes.clear()
var existing_selected_nodes: Array[String] = []
var lib = anim_player.get_animation_library(selected_library)
var has_animation = false
# Check the first animation in the library, to set the default selected state of the sprite nodes
if lib:
if lib.get_animation_list().size() > 0:
var first_anim = lib.get_animation(lib.get_animation_list()[0])
has_animation = true
for i in first_anim.get_track_count():
var path = first_anim.track_get_path(i)
if path.get_subname_count() > 0 and path.get_subname(0) == "frame" and path.get_name_count() > 0:
existing_selected_nodes.append(path.get_name(0))
for i in sprite_node_names.size():
if !has_animation or existing_selected_nodes.has(sprite_node_names[i]):
# If no animation in the library, default to true
# Or existing animation contains the node track, then its true as well
selected_sprite_nodes.append(true)
%SpriteNodeItemList.add_item(sprite_node_names[i], checked_tex, true)
else:
selected_sprite_nodes.append(false)
%SpriteNodeItemList.add_item(sprite_node_names[i], unchecked_tex, true)
%SpriteNodeItemList.set_item_icon_modulate(i, Color.WHITE)
func update_library_list():
lib_names = anim_player.get_animation_library_list()
%LibraryItemList.clear()
for i in lib_names.size():
var item_string: String
if lib_names[i] == "":
item_string = "[Global]"
else:
item_string = lib_names[i]
if lib_names[i] == selected_library:
%LibraryItemList.select(i)
item_string += " (selected)"
%LibraryItemList.add_item(item_string, null, true)
func update_visible_anim():
animation_parts.clear()
var lib = anim_player.get_animation_library(selected_library)
if !lib:
return
var visible_anims = lib.get_animation_list()
# convert all animation to MSAFPart
for anim_name in visible_anims:
var animation = lib.get_animation(anim_name)
var new_part = MSAFPart.new()
new_part.animation_name = anim_name
new_part.loop = animation.loop_mode != Animation.LOOP_NONE
if animation.get_track_count() > 0:
var key_count = animation.track_get_key_count(0)
if key_count > 1:
new_part.start_index = animation.track_get_key_value(0, 0)
new_part.end_index = animation.track_get_key_value(0, key_count - 1)
new_part.fps = key_count / animation.length
else:
new_part.start_index = animation.track_get_key_value(0, 0)
new_part.end_index = animation.track_get_key_value(0, 0)
new_part.fps = 1
else:
new_part.start_index = -1
new_part.end_index = -1
new_part.fps = -1
animation_parts.append(new_part)
func update_animation_list():
%AnimationItemList.clear()
for anim_part in animation_parts:
var item_string = anim_part.animation_name
if anim_part.loop:
item_string += " (loop)"
if anim_part.fps > 0:
item_string += " [%d - %d]" % [anim_part.start_index, anim_part.end_index]
item_string += " %.2f fps" % anim_part.fps
else:
item_string += " [? - ?] ? fps"
%AnimationItemList.add_item(item_string, null, true)
func _on_library_item_list_item_selected(index):
var previously_selected_lib = selected_library
if index < lib_names.size():
selected_library = lib_names[index]
if previously_selected_lib != selected_library:
if selected_library == "":
print("MSAF Selected library: [Global]")
else:
print("MSAF Selected library: ", selected_library)
refresh_all()
func _on_sprite_node_item_list_item_selected(index):
# toggle item
if selected_sprite_nodes[index]:
%SpriteNodeItemList.set_item_icon(index, unchecked_tex)
else:
%SpriteNodeItemList.set_item_icon(index, checked_tex)
selected_sprite_nodes[index] = !selected_sprite_nodes[index]
func _on_select_all_button_pressed():
print("MSAF select all sprite nodes")
for i in sprite_node_names.size():
%SpriteNodeItemList.set_item_icon(i, checked_tex)
selected_sprite_nodes[i] = true
func _on_select_none_button_pressed():
print("MSAF select none sprite nodes")
for i in sprite_node_names.size():
%SpriteNodeItemList.set_item_icon(i, unchecked_tex)
selected_sprite_nodes[i] = false
func _on_delete_anim_button_pressed():
var selected_item_indexes = %AnimationItemList.get_selected_items()
if selected_item_indexes.size() > 0:
var selected_index = selected_item_indexes[0]
print("MSAF deleted animation: ", animation_parts[selected_index].animation_name)
animation_parts.remove_at(selected_index)
update_animation_list()
%ChangeNotAppliedLabel.visible = true
func _on_add_anim_button_pressed():
print("MSAF added new animation")
if %AnimNameLineEdit.text == "" or %AnimNameLineEdit.text.contains("/"):
$AcceptDialog.dialog_text = "Invalid animation name"
%AcceptDialog.popup_centered()
return
if !%StartFrameLineEdit.text.is_valid_int() or !%EndFrameLineEdit.text.is_valid_int():
$AcceptDialog.dialog_text = "Start and end frame needs to be integer"
%AcceptDialog.popup_centered()
return
if !%FPSLineEdit.text.is_valid_float() and float(%FPSLineEdit.text) <= 0:
$AcceptDialog.dialog_text = "Invalid FPS number"
%AcceptDialog.popup_centered()
return
var new_part = MSAFPart.new()
new_part.animation_name = %AnimNameLineEdit.text
new_part.loop = %LoopCheckButton.button_pressed
new_part.start_index = int(%StartFrameLineEdit.text)
new_part.end_index = int(%EndFrameLineEdit.text)
new_part.fps = float(%FPSLineEdit.text)
animation_parts.append(new_part)
update_animation_list()
%ChangeNotAppliedLabel.visible = true
func _on_generate_button_pressed():
var lib = anim_player.get_animation_library(selected_library)
if !lib:
$AcceptDialog.dialog_text = "No library selected"
%AcceptDialog.popup_centered()
return
if %OverwriteCheckBox.button_pressed: # overwrite is checked
for existing_anim in lib.get_animation_list():
lib.remove_animation(existing_anim)
for anim_part in animation_parts:
if anim_part.fps <= 0:
# invalid animation part, skip this one
continue
if lib.has_animation(anim_part.animation_name): # if already exist
if !%OverwriteCheckBox.button_pressed: # overwrite is not checked
continue # skip this one
var animation = Animation.new()
animation.length = float(anim_part.end_index - anim_part.start_index + 1) / anim_part.fps
if anim_part.loop:
animation.loop_mode = Animation.LOOP_LINEAR
else:
animation.loop_mode = Animation.LOOP_NONE
for i in sprite_node_names.size():
if !selected_sprite_nodes[i]:
# this sprite node is not selected, skip it
continue
# add a track for each sprite node
animation.add_track(Animation.TYPE_VALUE)
animation.value_track_set_update_mode(i, Animation.UPDATE_DISCRETE)
animation.track_set_path(i, "%s:frame" % sprite_node_names[i])
# add a the frames to the track
for j in range(anim_part.start_index, anim_part.end_index + 1):
animation.track_insert_key(i, float(j - anim_part.start_index) / anim_part.fps, j)
lib.add_animation(anim_part.animation_name, animation)
%ChangeNotAppliedLabel.visible = false
refresh_all()
func _on_refresh_button_pressed():
refresh_all()

View file

@ -1,209 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://dh4eckdue2vu"]
[ext_resource type="Script" path="res://addons/modular_sprite_animation_factory/dock/msaf_dock.gd" id="1_0o686"]
[node name="MSAF" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_0o686")
[node name="ScrollContainer" type="ScrollContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
horizontal_scroll_mode = 0
[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 10
[node name="LibraryTitle" type="Label" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Animation Library"
horizontal_alignment = 1
[node name="LibraryItemList" type="ItemList" parent="ScrollContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
allow_reselect = true
allow_search = false
auto_height = true
[node name="Separator0" type="ColorRect" parent="ScrollContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
[node name="SpriteNodeTitle" type="Label" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Sprite2D nodes"
horizontal_alignment = 1
[node name="SpriteNodeItemList" type="ItemList" parent="ScrollContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
allow_reselect = true
allow_search = false
auto_height = true
icon_scale = 0.05
[node name="HBoxContainer5" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="SelectAllButton" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer5"]
layout_mode = 2
text = "Select all"
[node name="SelectNoneButton" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer5"]
layout_mode = 2
text = "Select none"
[node name="Separator1" type="ColorRect" parent="ScrollContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
[node name="AnimationTitle" type="Label" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Animations"
horizontal_alignment = 1
[node name="AnimationItemList" type="ItemList" parent="ScrollContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
allow_search = false
auto_height = true
[node name="DeleteAnimButton" type="Button" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Delete selected animation"
[node name="NewAnimTitle" type="Label" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "New animation"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer"]
custom_minimum_size = Vector2(140, 0)
layout_mode = 2
text = "Animation name: "
[node name="AnimNameLineEdit" type="LineEdit" parent="ScrollContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "i.e. Idle, Walk, Run, Jump, etc"
[node name="HBoxContainer3" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
[node name="Label2" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer3"]
custom_minimum_size = Vector2(140, 0)
layout_mode = 2
text = "Loop:"
[node name="LoopCheckButton" type="CheckButton" parent="ScrollContainer/VBoxContainer/HBoxContainer3"]
unique_name_in_owner = true
layout_mode = 2
[node name="HBoxContainer2" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer2"]
custom_minimum_size = Vector2(140, 0)
layout_mode = 2
text = "Start frame:"
[node name="StartFrameLineEdit" type="LineEdit" parent="ScrollContainer/VBoxContainer/HBoxContainer2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "int"
[node name="HBoxContainer4" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
[node name="Label2" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer4"]
custom_minimum_size = Vector2(140, 0)
layout_mode = 2
text = "End frame:"
[node name="EndFrameLineEdit" type="LineEdit" parent="ScrollContainer/VBoxContainer/HBoxContainer4"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "int"
[node name="HBoxContainer6" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
[node name="Label2" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer6"]
custom_minimum_size = Vector2(140, 0)
layout_mode = 2
text = "FPS:"
[node name="FPSLineEdit" type="LineEdit" parent="ScrollContainer/VBoxContainer/HBoxContainer6"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "float"
[node name="AddAnimButton" type="Button" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Add new animation"
[node name="Separator2" type="ColorRect" parent="ScrollContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
[node name="ChangeNotAppliedLabel" type="Label" parent="ScrollContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
theme_override_colors/font_color = Color(1, 0.25, 0.25, 1)
text = "*Changes not applied until you click on Generate"
autowrap_mode = 2
[node name="HBoxContainer7" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer7"]
custom_minimum_size = Vector2(140, 0)
layout_mode = 2
text = "Overwrite existing?"
[node name="OverwriteCheckBox" type="CheckBox" parent="ScrollContainer/VBoxContainer/HBoxContainer7"]
unique_name_in_owner = true
layout_mode = 2
[node name="GenerateButton" type="Button" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Generate"
[node name="RefreshButton" type="Button" parent="ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Refresh"
[node name="AcceptDialog" type="AcceptDialog" parent="."]
unique_name_in_owner = true
title = "Error"
[connection signal="item_selected" from="ScrollContainer/VBoxContainer/LibraryItemList" to="." method="_on_library_item_list_item_selected"]
[connection signal="item_selected" from="ScrollContainer/VBoxContainer/SpriteNodeItemList" to="." method="_on_sprite_node_item_list_item_selected"]
[connection signal="pressed" from="ScrollContainer/VBoxContainer/HBoxContainer5/SelectAllButton" to="." method="_on_select_all_button_pressed"]
[connection signal="pressed" from="ScrollContainer/VBoxContainer/HBoxContainer5/SelectNoneButton" to="." method="_on_select_none_button_pressed"]
[connection signal="pressed" from="ScrollContainer/VBoxContainer/DeleteAnimButton" to="." method="_on_delete_anim_button_pressed"]
[connection signal="pressed" from="ScrollContainer/VBoxContainer/AddAnimButton" to="." method="_on_add_anim_button_pressed"]
[connection signal="pressed" from="ScrollContainer/VBoxContainer/GenerateButton" to="." method="_on_generate_button_pressed"]
[connection signal="pressed" from="ScrollContainer/VBoxContainer/RefreshButton" to="." method="_on_refresh_button_pressed"]

Binary file not shown.

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://byxf0djhsanrb"
path="res://.godot/imported/msaf_logo.png-60acddc1a9644cdd9dd997f1d7e8732c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/modular_sprite_animation_factory/msaf_logo.png"
dest_files=["res://.godot/imported/msaf_logo.png-60acddc1a9644cdd9dd997f1d7e8732c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -1,9 +0,0 @@
extends Object
class_name MSAFPart
@export var animation_name: String
@export var start_index: int
@export var end_index: int
@export var fps: float
@export var loop: bool

View file

@ -1,7 +0,0 @@
[plugin]
name="Modular Sprite Animation Factory"
description="A plugin to generate animations for modular 2d sprites. Generated animations will have multiple tracks, one for each Sprite2D node."
author="kyboon"
version="1.0.1"
script="plugin.gd"

View file

@ -1,57 +0,0 @@
@tool
extends EditorPlugin
const AUTOLOAD_NAME = "ModularSpriteAnimationFactory"
var dock
func _enter_tree():
dock = preload("res://addons/modular_sprite_animation_factory/dock/msaf_dock.tscn").instantiate()
func _exit_tree():
dock.queue_free()
func _handles(object):
return object_is_valid_candidate(object)
func _edit(object):
if object:
if !dock.get_parent():
add_control_to_dock(EditorPlugin.DOCK_SLOT_RIGHT_UL, dock)
var sprite_children = get_sprite_2d_children(object)
var anim_children = get_anim_player_children(object)
dock.setup_dock(sprite_children.map(get_node_name), anim_children[0])
else:
remove_control_from_docks(dock)
func object_is_valid_candidate(object):
# The heirachy should be as below
# - Node2D
# - AnimationPlayer
# - Sprite2D 1
# - Sprite2D 2
# - ...
# When selected the parent Node2D, handles it
if object and object is Node2D:
var children = object.get_children()
return children.any(is_anim_player) and children.any(is_sprite_2d)
return false
func is_sprite_2d(object):
return object is Sprite2D
func is_anim_player(object):
return object is AnimationPlayer
func get_node_name(object):
return object.name
func get_sprite_2d_children(object: Node2D):
var children = object.get_children()
return children.filter(is_sprite_2d)
func get_anim_player_children(object: Node2D):
var children = object.get_children()
return children.filter(is_anim_player)