Closed metaphoricalsasquash closed 5 years ago
Is this not a bug? I cannot believe this is how it was intended to work.
It's probably not a bug, unless I'm missing something. There is a lot mentioned in the topic, so I wasn't too sure exactly where the focus was for it.
Regarding the steps to reproduce.
At least on my end HFrames to 3 corrects the animation. Edit - Am I missing something?
There is no way to know what's actually on the sprite sheet. It just uses row and column math to slice it up into identical rectangles. You'll always have to specify these numbers and conform a spritesheet to fit that alignment.
As far as the workflow things, if you want to keep your keyframes correct, as you were saying, additions will probably have to go on the end. I'm not exactly sure what kind of algorithm you could use that will know where you want to offset the values of existing keyframes to match the insertions into the middle of an updated spritesheet.
There is still nothing that knows the content of your spritesheet or what you want at what location.
In my experience at least, when I mangle these things in a large project, its just best to write a toolscript to automate the adjustments and fixes of AnimationPlayer keyframes. Otherwise if its small, doing it by hand may be fastest.
There is no way to know what's actually on the sprite sheet.
Godot does not need to know what's on the sprite sheet. All it needs to know is that I when I add a column (increase of Hframes) it will change all already existing keyframes with the "frame:" value according to the algorithm proposed in the solution above.
I do not see how this is not a bug, to be honest: If you already have keyframes set for your frame-by-frame animation, why would you want the displayed frames of already set keyframes change arbitrarily, only because you add a column or row to your spritesheet?
It makes iteration impossible, because it forces you to either have a fixed number of animations or a fixed number of frames per animation when you start your project. The only case when this would be less of a problem/bug is when you are creating an exact clone or mini game and you how exactly how many animations or how many frames you will need. But are these the the only kind of games we want for this engine?
At least on my end HFrames to 3 corrects the animation.
Sadly it does not. What this does and what your gif shows is that it defines the correct cell size of the sprite sheet. What breaks the animation is that different cells are shown. Because "frame:" counts the cells from left to right until the end of the first row, then the second row from left to right and so on. Maybe make sure your animation plays slow, you can pause and see what frame it used to be, I've written it below the number of the current keyframe. The red frame for instance is 10, while it was and still should be 7.
If this would be a runcycle, the character would not run anymore because the frames would be all mixed up. I will add another example with a runcycle when I get home, maybe the issue is easier and quicker to grasp then. It will be a few hours though.
I'm curious, are there any examples you have showing another game engine doing this kind of re-sequencing?
Pretty sure this is how the sprite sheets are designed, so it wouldn't be a "bug".
The idea behind it in the current form is that as long as you keep your frames in some kind of sequence going from left to right, top to bottom, it doesn't matter how you arrange the sheets. The frames should still read in the correct frame order.
Like doing this for example, wouldn't break your animation keyframes.
So you need to add some frames to this 2x8 sheet later, they would go in positions to the right of 11 and wrap into the new row. And if you have a new row, increase it.
You would just have to organize and export your spritesheets to maintain this order, and nothing should break later.
I think I understand that you have some particular workflow you want accommodated, where you use completely symmetrical spritesheets, and need to extend or contract all cycles uniformly? Again, not entirely sure. It sounds at least like you want to toss in a new column, update the frame count, and have the engine modify all your keyframes in all animation players and animations that use that sprite sheet.
If that is roughly it, then what you're suggesting solves perhaps only just for that, but what about non-uniform spritesheets?
In my work at least, we stuff in animations of all differing lengths, and rarely do we have a set that even give us perfectly filled sheets.
In my case, having an update to a spritesheet property do widespread changes to the keyframes is undesirable. I would think just the action of fiddling with the Hframe and Vframe properties will start mangling all our keyframes if it was making assumptions about how its organized.
hey avencherus, first of all, thank you sticking with me and trying to understand my arguments, I really appreciate it!
I have no experience using large spritesheets and frame-by-frame animation in other engines, so sadly I cannot give you an example how this would be dealt with elsewhere.
The idea behind it in the current form is that as long as you keep your frames in some kind of sequence going from left to right, top to bottom, it doesn't matter how you arrange the sheets. The frames should still read in the correct frame order.
Yes I know. That's precisely the root of the problem. I do not think I have a particular workflow I want accommodated, the issue applies to the workflow you explained in your last comment just the same as soon as you want iteration and more than a few animations in a single sprite sheet for drawcall and performance reasons.
Please bear with me while I try to explain: If you know of any other way or option to organize, edit, manage and maintain larger amount of animations in a spritesheet, please do share.
Oh and thanks for proposing a solution (From 6 by 2 to 2 by 8)! While this is certainly feasibly for small projects and small Spritesheets, I do not see how it would be feasible for regular sized professional productions meaning anything more than 20 animations per sheet. Essentially, you would have to do the same tedious restructuring with the only difference being you would have to do it outside of Godot. Plus, if you do this for a while you get really "unreadable" spritesheets. So for me, that's actually even a bit worse than reassigning keyframe values inside Godot.
No problem, I'm just trying to at least understand what you have in mind. This is a very nice graphic you've made.
And apologies, what you've outlined is all new to me. This is my first time seeing anyone organize spritesheets that way, so maybe I'm completely in the dark about something.
There are basically two ways to organize frame by frame animation.
I did not see our way in there, so you may feel this is illegitimate. X)
That's the order we go with and it fits well with how Godot functions presently. Yes, if we have to expand the frame count, well we have to just bite the bullet and re-keyframe some things. It has been done a couple times and it only takes a few minutes for a dozen or so animations.
My impression of what you have explained above is that there appears to be a lot of wasted space in there. This examples is a 15x11 and has 47 empty frames. (28% empty?)
When I think about a 400x300ish frame size it would amount to 400x300x47 = 5,640,000 dead pixels. Spritesheets already tend to be somewhat wasteful in favor of convenience, but just speaking for myself I wouldn't want to voluntarily take on so much more for this method.
If I were to try to put what you have into my own words, it resembles to me something like sub-spritesheets inside of spritesheets, or possibly a hybrid between a spritesheet and an atlas. An atlas with the requirements that a texture be in a uniform size and then be organized in some adjacent manner.
Unfortunately, I really think I'd have to see this one implemented in the wild and in practice to understand and evaluate it.
The only downside I see with dead pixels is a larger download. The upside is a MUCH better overview, which is absolute indispensable, when you are doing pixelart, get more animations and frames and lower resolution sprites. Currently I'm working on a 2D Pixelart project (something Godot praises itself for being a great fit) which means I have tons of frames that look almost indistinguishable next to each other. On top of that, naming each frame even each animation is impossible with frames just 32 pixel or 48 pixel wide which also have to accommodate the sprite. My current (very incomplete) player base sprite has 67 rows and 8 columns, so 535 frames. The png is 112KB in size, so I honestly don't care a bit about unused pixels on my spritesheet. Even if it would be ten times as large, the ability to find animations and frames I'm looking for outweighs the 0.01 seconds additional download time a billion to one. I know you are not doing pixelart in your game (which looks absolutely awesome btw! I've been following for a while) but in pixelart animation you select move and copy previously created frames and past them into new animations all the time. That's the core of any pixelart animation. Every single pixelpush has a huge impact to your animation. So the ability to quicky jump through your spritesheet, find what you are looking for copy and paste it to someplace else in your spritesheet or compare single pixel locations from various places in your sheet, is absolutely necessary. You also have to do this because your newly created frame must match previously created ones by the pixel. Think a change from one idle into another.
Yes, if we have to expand the frame count, well we have to just bite the bullet and re-keyframe some things. It has been done a couple times and it only takes a few minutes for a dozen or so animations.
This is what this issue is about. For you it might be not that much of an issue. I suppose this is because you are not making a pixel game and because you are making a sidescoller with two directions of movement, not 8. Hence your spritesheets are a lot more clearly laid out by default and while the re-keyframing or rearranging of your spritesheets might be an inconvenience, it is not so much an issue. For me however, and I dare say anyone who wants to do a slightly more professional looking pixel art game with decently complex animation, I dare say it not just an inconvenient issue, it's clearly a Starship Trooper sized brain bug in Godots design. I therefore would really appreciate if someone would review the "enhancement" tag and maybe consider replacing it with a "bug" tag.
I did not see our way in there, so you may feel this is illegitimate
You way or organizing the spritesheet is just as legitimate as any other. It is however affected by this issue just the same. Hence not a solution. When scaling up production, your way of organizing it would fail exactly like the other options I've layed out so far. And for the same reason: because keyframes don't update their "frame:value" when HFrames changes. So you either end up having to rework all the sprites in your spritesheet externally and make the spritesheet less readable in the process, or re-set all keyframe "frame:" values in Godot.
I don't understand this issue. What you are asking is not something any framework/engine I've used before supports. How do you expect Godot to understand that the image that you told it had 67 rows and 8 columns now has 70 rows and 8 columns and it should magically (?) offset all the frames of the other animations? That image doesn't even know that it has animations linked to it. Making sense of where one animation starts and when it ends is your job or yours programmer job. Godot doesn't know that your first row is the "walk" animation and your second is the "run" animation that's something you tell it and you will need to update if you change anything that affects it. The only thing that Godot knows and cares is that an image has x
rows and y
columns and uses that information to calculate where in that image the frame 10 is anything else is up to you.
Also, transparent pixels are still uploaded to the GPU and taking space in the video memory. PNGs are compressed lossless image files but the data you upload to the GPU is uncompressed so that 112KB png file is ~2.2MB uncompressed if my math isn't wrong (which isn't much but you can see why it can add up to a lot and why there are tools like TexturePacker that can remove all the transparent pixels around the sprite and pack them tightly into a smaller image). It has nothing to do with download speeds.
What you are asking is not something any framework/engine I've used before supports. How do you expect Godot to understand that the image that you told it had 67 rows and 8 columns now has 70 rows and 8 columns and it should magically (?) offset all the frames of the other animations? That image doesn't even know that it has animations linked to it. Making sense of where one animation starts and when it ends is your job or yours programmer job. Godot doesn't know that your first row is the "walk" animation and your second is the "run" animation that's something you tell it and you will need to update if you change anything that affects it.
I'm not asking for any of that. Please have a look at my proposal again.
The only thing that Godot knows and cares is that an image has x rows and y columns and uses that information to calculate where in that image the frame 10 is anything else is up to you.
Yes I know. If it remembers what the previous setting for Hframes and Vframes was and what the current new setting is, that's also all it needs to know to fix the issue and adjust keyframes with "frame:" values.
Also, transparent pixels are still uploaded to the GPU and taking space in the video memory. PNGs are compressed lossless image files but the data you upload to the GPU is uncompressed so that 112KB png file is ~2.2MB uncompressed if my math isn't wrong
Thank you for pointing this out. I was not sure about how the GPU handles the png compression. Still, even 22 MB uncompressed are nothing compared to an inability to iterate on animation, add frames or add animations in the production process. Texture Packer makes a lot of sense for Tilemaps in 2D HD games, not so much for animation in low res 2D pixelart games in Godot. At least I would not know how you could marry those two when it comes to frame-by-frame pixel animation. If you know, or have a tool, please let us know.
It does make sense in 2D pixelart games. For example, I had to package all the sprites of this game I worked on https://store.steampowered.com/app/462100/Starr_Mazer_DSP/ (this isn't a Godot game) into big spritesheets because we were having issues running out of vram on mobile (although we didn't end releasing it on mobile) Like this:
(the spritesheets are transparent but windows is being windows)
Those are ~14200 sprites (most of them is the japanese font ~10k 😅 )
The position of your sprites in the spritesheet doesn't matter because it's you (or your programmer) the one that will give meaning to it.
Yes I know. If it remembers what the previous setting for Hframes and Vframes was and what the current new setting is, that's also all it needs to know to fix the issue and adjust keyframes with "frame:" values.
The Sprite doesn't know that it has animations linked to it and the AnimationPlayer just has a track that points to a property of a node (in this case to the frame
property of a Sprite) and doesn't know anything else about it (it doesn't even know that it's pointing to a specific Sprite just a NodePath)
Wow, congrats on working on such a beautiful game!
Of course .. TexturePacker can make a lot of sense even for pixel games, depending on your target platform ect ... If you want to release on C64, you most likely will have to dig much deeper than TexturePacker to make things work.
The Sprite doesn't know that it has animations linked to it and the AnimationPlayer just has a track that points to a property of a node (in this case to the frame property of a Sprite) and doesn't know anything else about it (it doesn't even know that it's pointing to a specific Sprite just a NodePath)
So maybe the Animation Player should be notified when there is a change made of a Hframes property down the Node Path? What's wrong with having the Sprite Node emitting a signal to do just that?
The position of your sprites in the spritesheet doesn't matter because it's you (or your programmer) the one that will give meaning to it.
It does matter a whole lot to whoever is in the process of creating the spritesheet and keyframes if they have an interest to stay mentally sane. Once they are all done you are totally right. You can scramble and optimize the sprite frames order and position to their most efficient arrangement. That is as long as your code is supporting the simultaneous and automatic re-setting of your "frame:" values in all your keyframes. But if we would have this functionality in Godot already, we would not need to have this discussion here in the first place.
Hey guys I made another graphic, in hopes it's easier to understand for people hearing about this the first time, let me know what you think:
@groud and others who have labeling rights: I kindly request the "enhancement" label to be reviewed. Please have a look at the graphic I made. If you still don't think this is a bug, please be so kind and help me understand how this could be intended behavior. It makes spritesheet work hard for no benefit and the trouble the issue causes increases exponentially with the size of the project. Everyone, no matter what their workflow is or how they structure their spritesheet or whether or not they use a spritesheet packer tool or not, everyone has to deal with this issue and the additional workload it creates. A workload, that becomes unfeasible to manage if the project becomes large.
We do not have an option yet to import timing for animation, so when designing our animation, we are depended on keyframes. I'm just at the beginning of incorporating animation into my project. Luckily, I haven't set all my keyframes yet, just a tiny percentage. Still, I had to meticulously and painstakingly spend hours and hours selecting each frame, on every track on every animation, comparing the previous value with my desired current one and reset it, all the while praying I don't fuck up. There is no point in doing this. It's tedious and an invite for error. How was this ever intended behavior? And even if it was, it's buggy as hell.
I'm trying to use AnimatedSprites controlled by AnimationPlayer not even using spritesheets.. but individual, animated .png's. "Only" trying to get it somehow to work since about 40 hours. There is zero documentation for frame-animation. There's a few examples... but none of them go into different animations: Always a single kind of animation. When asking in help not enough people seem to be using this kind of animation as programmers probably just use some cutout sprites and stick to AnimationPlayer. I've set myself some workflow with other applications where I can decently animate something new and simple within 5 minutes or less. And I'm sure I'm not the only one who prefers NOT to directly animate in Godot if a different, more efficient pipeline is already setup. Please... do not enforce people to rigid workflows.. but enable them to use whatever they need. By: Enabling simple use of individual .pngs or Spritesheets in AnimatedSprites.. and letting those be controlled through AnimationPlayer. This is not about "enhacement". In the current state.. it seems impossible to actually use and get anything done. When I try to change the played Animation in AnimationPlayer... the only keyframed Animations played are actually the ones selected in "Animation" property of the AnimatedSprite. Having different animations in AnimatedSprites. Therefore completely has no effect. I am now forced to use a separate "AnimatedSprite" for each kind of animation. However that leads to all animations being shown on screen at once. This cumbersome workflow can't be intended by design: Especially since both AnimatedSprites and AnimationPlayer already have separate tracks for different animation-types... built... in.
I also have this issue and think it is a bug!
Let makes things clear. A bug is when something happens in a way it was not designed for. No one designed Godot to keep the indices if you change your texture size, it is written down nowhere in the documentation. So right now, everything works as expected (indeed from the developers point of view), even if the current design has limitations.
I do not mean to minimize the problem, the enhancement would be a significant improvement. But no, it is not a bug.
A bug is when something happens in a way it was not designed for.
The design is to let the user assign a specific keyframe. Godot was not designed to change the displayed keyframe once it has been assigned unless the user resigns it. It works as specified in the design when expanding vertically. But not horizontally. Godot is also designed to allow changes in the spritesheet dimension. (HFrame and VFrame Inspector settings).
To me that's as clear cut a bug as the definition can be. The way I read and understand it, also according to your own definition.
Godot was not designed to change the displayed keyframe once it has been assigned unless the user resigns it.
You are wrong here, it was designed to work that way. The indices are, by design, naturally set from left to right then from top to bottom. So yeah, if you extend the texture horizontally, the indices get offset.
It is said nowhere the indices should be kept when you change the texture size, and event if we did, people might even complain because their indices could go unordered when changing from one texture to another. It might even be compatibility breaking. So for now, by design, Godot does not support changing the size of your texture while keeping the indices. That's all.
To be honest, it is more like "we did not think about this problem when we designed it", but that's the definition of an enhancement : it works as expected, we know it has limitations, but everything happening here is completely expected.
But also, I don't want to be mean but I would prefer not to have this kind of discussions. We are the ones working on fixing those issues, so please, respect the way we organize the work to be done. Unless if other contributors agree the issue should be moved to bugs, the tags are not going to change.
Anyway, I might be able to solve the problem easily. I'll try something.
please, respect the way we organize the work to be done
I certainly do. So far noone has explained why this would be intended behavior and I am completely unfamiliar with the usecase you mention here.
Ummmm, why this is closed? Newb here. Is there a solution already? What is this "frame_coords" thing and how does it work? Thank you devs for your hard work btw xD
Groud made a pull request and already committed the fix: https://github.com/godotengine/godot/pull/25327 Above your comment you can see the purple graphic saying the pull request has been merged and added to Godot 3.2
@akien-mga Please reopen this issue (not sure if OP is still around) https://github.com/godotengine/godot/pull/25327 does not fix this issue at all, animating the Sprite Frame property is still incredibly broken in 3.2 Alpha2 as described in the original post of this issue. I have a lot of animations and would really need to have this fixed.
Minimal test project: expand_spritesheet.zip Run the project, click on the color buttons to see a spritesheet animation playing. Each animation plays a separate row of the "test_spritesheet.png" spritesheet.
To test the issue,
25327 does not fix this issue at all, animating the Sprite Frame property is still incredibly broken in 3.2 Alpha2 as described in the original post of this issue.
This is not broken, as I already explained this is the expected behavior. This is once again NOT a bug and it is up to you to now change the way you deal with your animations. This should be doable via a script though, using the Animation API.
It is not expected by users as you can see here in this thread.
Maybe you wrote it this way, or studied the source code intensively, then of course you expect to behave it like that, but users of the Sprite Frame property obviously don't expect this behavior at all.
How should they expect this behaviour? What would be the underlying intention of a design that allows spritesheets to be extended only vertically, not horizontally? If that's a feature, it's the most stupid feature I've ever heard of. This "feature" effectively breaks animation as demonstrated in the minimal project and the thorough description of the original post.
If you don't want to call it a bug, it's very bad design at the very least. What ever you call it, it really needs fixing. I therefore once again ask like @jaacko-torus for this issue to be reopened.
I am once again, going to explain how the frame property works within the engine: you select a frame, which is numbered from left to right, then from top to bottom. So it is expected so that changing the number of column changes the ID of your frames. It's easy to understand, and without considering this texture resize problem, it does the job quite well.
It is not expected by users as you can see here in this thread.
Sorry, but this issue did not receive enough upvotes to be significantly representative about how the feature should work. But anyway, what users think is not what matters to define what is a bug or not. A bug happens when a software does not behave as expected from the programmer point of view, not the user one. The user might just have, like here apparently, misunderstood how the feature was designed and the implied advantages/flaws. So the only bug here is maybe about adding a warning to the documentation, but I don't really call that a bug.
If you don't want to call it a bug, it's very bad design at the very least.
Yeah, in that case we can call it bad design. So for now this issue will not be opened again as this is not a bug, and you can now easily workaround it using the frame_coords
feature. The update the "frame" animation to the "frame_coord" animation is another problem though, so if you face problem updating this should be another issue.
If you have a better design in mind, please open an issue on the godot-proposal repository.
A bug happens when a software does not behave as expected from the programmer point of view, not the user one
Have you ever worked with a QA team? You don't see the problem with this philosophy at all?
Yeah, in that case we can call it bad design. So for now this issue will not be opened again as this is not a bug
This issue was not labeled as bug. To be reopend it does not need to be labeled as bug. You yourself labeled it as " enhancement topic:editor usability" I asked @akien-mga who closed it to reopen it, because nothing about it has been fixed. And it still needs fixing!
you can now easily workaround it using the frame_coords feature.
No you cannot. This would mean destroying and completely redoing each and every single Animation. In my case that's a year's worth of work.
Once again, this issue is about the Frame property. Not the newly added Coords. If the Frame property is still available in the engine, it still needs fixing.
explain how the frame property works within the engine: you select a frame, which is numbered from left to right, then from top to bottom.
This is not how the Frame property works for the user. The frame property expects an integer. The user therefore expects the same behavior if the spritesheet is expanded vertically or horizontally, again, see OPs graphic in the original post.
If you have a better design in mind, please open an issue on the godot-proposal repository.
The original post already has a fix proposed: The cell IDs have to update if the Hframe property changed.
Have you ever worked with a QA team? You don't see the problem with this philosophy at all?
Lol, I actually did. And changing something like this would definitely be something we would not change for free. And that would also be something where we would be paid to do some hack because the client does not understand a word about its own tools.
No you cannot. This would mean destroying and completely redoing each and every single Animation. In my case that's a year's worth of work. Once again, this issue is about the Frame property. Not the newly added Coords. If the Frame property is still available in the engine, it still needs fixing.
Yeah, that's a year of work. Next time you will have to think a little bit more about how a feature works before using it. And we won't solve your problem by introducing workarounds in the code, sorry. And once again, there is nothing to fix here, unless you have a real "solution" to the problem. Otherwise, stop wasting our time.
Yeah, that's a year of work. Next time you will have to think a little bit more about how a feature works before using it. And we won't solve your problem by introducing workarounds in the code, sorry. And once again, there is nothing to fix here, unless you have a real "solution" to the problem. Otherwise, stop wasting our time.
What the hell?
Alright guys, locking.
What is asked here is not possible with the way spriteframes work in Godot, and a proxy parameter was added to allow the use case described here without breaking compatibility.
If you want the frame property to follow a different logic, or be removed and replaced altogether, this is a breaking change and it should be discussed (constructively) on https://github.com/godotengine/godot-proposals.
Godot version: 3.0.6, 3.0.7, 3.1.alpha.calinou.c320d93
OS/device including version: Win7Pro 64bit, Intel-internal/NVIDIA
Issue description: Working in Frame-by-frame Animation with Spritesheets is a bit tedious right now, see discussion here: 12469 However another, maybe far more important issue, is the exponential workload created when adding frames to an existing animation in a spritesheet animation. This makes iteration almost impossible. Adding frames to the bottom of the spritesheet is no problem at all, as increasing the Vframe does not change existing keyframes. Adding frames horizontally however, breaks the animations, because frame: count the cells in the spritesheet from left to right and keyframes don't update their "frame:" value to added cells in every row.
My current workaround involves numbering each frame in the spritesheet with current and previous keyframe numbers in an external graphics editor, then go to every Animation and every track and every keyframe and manually set the new value. I hope you can see how crazy this is and becomes even more so the more animations/tracks/keyframes you have. In addition to the stupidity of the task, it's super easy to incorporate mistakes in the procedure, and hence demands a lot of concentration. I do not wish this job on my fiercest enemy.
Proposed solution: Update Keyframe value "frame:" when Hframes changed depending on what VFrame the frame: was set and how many Hframes where added. For instance:
Hframes =+1: Keyframe in VFrame row 0: update frame: value = value Keyframe in VFrame row 1: update frame: value =-1 Keyframe in VFrame row 5: update frame: value =-5
Hframes =+3: Keyframe in VFrame row 0: update frame: value = value Keyframe in VFrame row 1: update frame: value =-3 Keyframe in VFrame row 5: update frame: value =-15
EDIT: I spend a day and a halve making another graphic in hopes newcomers to this issue can gasp it quickly:
Steps to reproduce: