Jump to content
lucid

SpriterPlusPlus - a C++ Spriter implementation

Recommended Posts

1 hour ago, lucid said:

Which animation is that?  Also it looks like the legs are in the normal position - does the animation play stably, or is there constant rotation and flipping of the whole character?

It is animation 0 (walking). With the animation 1 (idle), the first frame is correct (elapsedTime==0) but then the rest is going strange: parts of the body are  always turning in the same direction, no flipping. Here is how it looks like when it is the first frame by animation 1:

CF25LeftHanded2.png.9d1abe20c8fded4a368c

1 hour ago, lucid said:

Is this code used somewhere?

Yes, just below in the code posted above:

 childPosition.x = (preMult.x * angleCos) + (preMult.y * angleSin);
 childPosition.y = -(preMult.x * angleSin) + (preMult.y * angleCos);

I am also using it for bones to debug and I will certainly use something similar for points and boxes.

Share this post


Link to post
Share on other sites
5 hours ago, labsin said:

 

Instead of changing the values in the engine, you can overwrite them in your implementation with calling the following somewhere:


SpriterEngine::Settings::reverseYOnLoad = true;

You are right, thanks. I will change this.

Share this post


Link to post
Share on other sites

I was also not able to get these settings to work, Cocos2d-X also does not call for Y inverted, regardless of how I set those global variables I have to have code like the following to invert the y position and revert the y position on the (Pivot):

 

        sprite->setPosition(float(spriteInfo->getPosition().x), -float(spriteInfo->getPosition().y));
        sprite->setAnchorPoint(cc::Vec2(float(spriteInfo->getPivot().x), 1.0f - float(spriteInfo->getPivot().y)));

 

Share this post


Link to post
Share on other sites
42 minutes ago, conceptgame said:

but then the rest is going strange: parts of the body are  always turning in the same direction

@conceptgame There's no setting to do this (will add one if this solves your problem), but can you add this line:

spin*=-1;


after  

if(spinAtt->isValid())
{
	// ...
}

 in SpriterDocumentLoader.cpp as shown below:
 

UniversalObjectInterface *SpriterDocumentLoader::getObjectInfoFromTimelineKeyElement(SpriterFileElementWrapper *keyElement, Entity *entity, Object *object, Timeline *timeline, FileFlattener *fileFlattener, SpriteKeyFileInfo *spriteKeyFileInfo, SubEntityKeyInfo *subEntityKeyInfo, point *defaultBoxPivot)
{
	int spin = 1;
	SpriterFileAttributeWrapper *spinAtt = keyElement->getFirstAttribute("spin");
	if (spinAtt->isValid())
	{
		spin = spinAtt->getIntValue();
	}
     	
  	spin*=-1;

and let me know if it fixes your issue.
 

42 minutes ago, conceptgame said:

Yes, just below in the code posted above:

 childPosition.x = (preMult.x * angleCos) + (preMult.y * angleSin);
 childPosition.y = -(preMult.x * angleSin) + (preMult.y * angleCos);

Doesn't that cancel the effects of the reverse angle setting?

 

Quote

I was also not able to get these settings to work, Cocos2d-X also does not call for Y inverted, regardless of how I set those global variables I have to have code like the following to invert the y position and revert the y position on the (Pivot):

@jeremyjh Does it have no effect at all, or just not the desired effect?  If it has no effect, make sure you're setting those values before you initialize the SpriterModel object as it reverses the values upon loading.

Share this post


Link to post
Share on other sites
54 minutes ago, lucid said:

@conceptgame There's no setting to do this (will add one if this solves your problem), but can you add this line:


spin*=-1;

 

Thanks lucid, it has fixed the issue.

55 minutes ago, lucid said:

 

Doesn't that cancel the effects of the reverse angle setting?
 

I don't know anymore for what purpose is this setting. I will you use something similar for flipping but it is not a global but a dynamic use.

This change is for me compulsory otherwise it is completely wrong. It makes sense since most of the conventions are using right handed systems but not Direct3D.

I will be pleased to switch to OpenGL for the Android port.

Share this post


Link to post
Share on other sites
1 minute ago, conceptgame said:

Thanks lucid, it has fixed the issue.

Excellent.

1 minute ago, conceptgame said:

I don't know anymore for what purpose is this setting.

The setting (which should be set before the SpriterModel object is created, or at least before it loads a file), reverses the angles upon loading so engines that use clockwise or counterclockwise angles can just change this value instead of having to edit the internal code.  You can try removing your code changes to TransformProcessor and also changing the angle reversal setting and see if the result is the same.

Share this post


Link to post
Share on other sites
7 hours ago, lucid said:

 

@jeremyjh Does it have no effect at all, or just not the desired effect?  If it has no effect, make sure you're setting those values before you initialize the SpriterModel object as it reverses the values upon loading.

I played with it some more. The pivot setting actually does work as expected and I can remove my manipulation. But I get very jumbled output when I change the reverseYOnLoad to false. I do not simply see signs are reversed; I inserted some debug code and I get very different values for y when I change this to false. 

These are some values from the first frame when it is true:

Quote

Resources/GreyGuy/arms/p_arm_idle_a.png, y:-131.465888
Resources/GreyGuy/arms/p_forarm_walk_a.png, y:-107.752874
Resources/GreyGuy/hands/p_hand_a.png, y:-85.028443
Resources/GreyGuy/legs/p_thigh_a.png, y:-63.344628
Resources/GreyGuy/legs/p_leg_a.png, y:-44.117789

And when it is false:

Quote

Resources/GreyGuy/arms/p_arm_idle_a.png, y:-47.570174
Resources/GreyGuy/arms/p_forarm_walk_a.png, y:-27.821273
Resources/GreyGuy/hands/p_hand_a.png, y:-4.113247
Resources/GreyGuy/legs/p_thigh_a.png, y:13.048759
Resources/GreyGuy/legs/p_leg_a.png, y:35.245458

The animation only looks correct if I set it to true and then reverse the sign in render.

Share this post


Link to post
Share on other sites

That's odd.  When you reverse the sign in render, you're reversing the sign of y after all bone transformations have taken place?  If so, I might need to change the reverse y to do that instead of reversing y on load, since that would affect the pre-transformed values now that you mention it.

Share this post


Link to post
Share on other sites
8 hours ago, lucid said:

You can try removing your code changes to TransformProcessor and also changing the angle reversal setting and see if the result is the same.

Ok I see now. It would work if it would just be used there but it has an impact everywhere this value is used at the moment and won't have the desired effect.

It seems it is something similar as jeremyjh.

Share this post


Link to post
Share on other sites
9 hours ago, lucid said:

That's odd.  When you reverse the sign in render, you're reversing the sign of y after all bone transformations have taken place?  If so, I might need to change the reverse y to do that instead of reversing y on load, since that would affect the pre-transformed values now that you mention it.

Yes if the transformation code implicitly assumes an inverted Y axis. I can't quite think why it would matter. But that seems to be what is happening.

Share this post


Link to post
Share on other sites

Happy New Year 2016!

I have just few general questions about the interface with this implementation which can benefit others. What is the easiest and most performant way to do the following:

1) How to switch to another key frame (instead of changing time) from the current animation of an EntityInstance?

2) How to change entity (setCurrentEntity) by name instead of by index?

3) How to get name of the current animation or an animation by id and the number of animation for the current entity?

4) How to get the current key frame number in the current animation?

5) How to know if an animation is playing by name?

6) How to know if an animation is finished (animation not looped)? How to know if one loop was finished (loopable animation)?

 

Share this post


Link to post
Share on other sites
On 1/2/2016 at 4:09 PM, conceptgame said:

Happy New Year 2016!

I have just few general questions about the interface with this implementation which can benefit others. What is the easiest and most performant way to do the following:

1) How to switch to another key frame (instead of changing time) from the current animation of an EntityInstance?

2) How to change entity (setCurrentEntity) by name instead of by index?

3) How to get name of the current animation or an animation by id and the number of animation for the current entity?

4) How to get the current key frame number in the current animation?

5) How to know if an animation is playing by name?

6) How to know if an animation is finished (animation not looped)? How to know if one loop was finished (loopable animation)?

 

@conceptgame - Sorry for the late reply,  I must have accidentally dismissed the initial notification, because I didn't notice this post until I went to reply to @Banbury 's
2. Currently, each instance you create only contains the information and data structure for one entity (decided when you request the entity from the model).  Most of the code to support switching entities is already there for the sub-entity feature, so it should be pretty easy for me (or anyone else) to add this.  At the moment I'm working on the last couple of features and bug fixes for the upcoming version of Spriter (it's a big one, too).  If no one has gotten to it by then, I will add it.  

1,3,4,5,6 You can't do any of this yet, but it should all be fairly trivial to add, so I will put it on the todo list along with 2.  If anyone adds any of this before I do, please commit it to the main branch, and I will merge them.

On 1/10/2016 at 0:07 PM, Banbury said:

Is there a way to get information about a bone chain (e.g. a leg or an arm)? I would like to have the position, rotation and scale of all the bones in a chain at rendering time.

Same as above.  I should be able to add that when I'm done with the upcoming version of Spriter.

Share this post


Link to post
Share on other sites

If you're working on SpriterPlusPlus again, you might consider moving all the header files into a separate include directory. It makes using the library a lot easier. I did it on my own fork for my UE4 plugin.

Share this post


Link to post
Share on other sites

It completely makes sense lucid. I removed these functions in my current implementation when they are taking me more than 5 minutes to integrate.

On another hand, I experienced some issues which would be really useful:

- Blending animation where boxes exist in the second one but not the first one (and vice versa) gives an inapropriate result when getting position of the boxes. Is there a way to know that the box positions are valid or not when blending between two animations in the currrent implementation?

- Variables are crashing Spriter (I tried both last released version and beta version I think) when closing the popup window.

- Depending on the scml file, the bones are not drawn over the sprites.

- I cannot always delete a sound on the timeline. The sound stays even if alll the keyframes are deleted. Closing and opening again Spriter does not help.

I know that the 3 last ones are related to Spriter itself and should be moved to another thread.

Share this post


Link to post
Share on other sites
On 1/12/2016 at 0:00 PM, Banbury said:

If you're working on SpriterPlusPlus again, you might consider moving all the header files into a separate include directory.

You mean it makes it easier for working on the implementation itself?   To use the implementation you should only need the one include in the main directory.

 

44 minutes ago, conceptgame said:

- Blending animation where boxes exist in the second one but not the first one (and vice versa) gives an inapropriate result when getting position of the boxes. Is there a way to know that the box positions are valid or not when blending between two animations in the currrent implementation?

I meant to put this in the documentation, but it won't do any checks to make sure the hierarchies are equal.  I suppose it could be done with a separate function (that can be optionally called on command), but the reasoning is that it would be very slow (relatively speaking) to verify that both hierarchies are exactly the same.  I think it's best to just advise users that blending is made for two equal hierarchies, unless you have a use case where it makes sense to do otherwise.

 

 

44 minutes ago, conceptgame said:

Variables are crashing Spriter (I tried both last released version and beta version I think) when closing the popup window.

Someone else reported this, but I can't get it to crash with variables at all.  Does this happen every time for you?  If so, please send me a project where it does this if you can, so I can see if it's specific to certain projects.

44 minutes ago, conceptgame said:

Depending on the scml file, the bones are not drawn over the sprites.

This is in Spriter?  Please send me a project where the bones are not drawn on top as well. I've never seen this.

44 minutes ago, conceptgame said:

I cannot always delete a sound on the timeline. The sound stays even if alll the keyframes are deleted. Closing and opening again Spriter does not help

I will look into this.

 



Hopefully I can have these all fixed for the upcoming version.

Share this post


Link to post
Share on other sites
35 minutes ago, lucid said:

I meant to put this in the documentation, but it won't do any checks to make sure the hierarchies are equal.  I suppose it could be done with a separate function (that can be optionally called on command), but the reasoning is that it would be very slow (relatively speaking) to verify that both hierarchies are exactly the same.  I think it's best to just advise users that blending is made for two equal hierarchies, unless you have a use case where it makes sense to do otherwise.

Ok I did not think about this. I understand the point. I need to explain it well for beginner users in my documentation

35 minutes ago, lucid said:

Someone else reported this, but I can't get it to crash with variables at all.  Does this happen every time for you?  If so, please send me a project where it does this if you can, so I can see if it's specific to certain projects.

It happens every time. I used the last version of the Brutus Boss of the AdventurePlatformer full package and just add a variable.

35 minutes ago, lucid said:

This is in Spriter?  Please send me a project where the bones are not drawn on top as well. I've never seen this.

Sorry this one is in the current C++ implementation, not Spriter. I cannot explain why it should come from my implementation: it is working with BrutusBoss, WonkySkeleton and others but not for the GreyGuy for example. Weird issue. I am not sure that it is the ZOrder which is the problem.

Edit: I cannot attach screenshots (even smaller than 378Kb) to show you.

Share this post


Link to post
Share on other sites
28 minutes ago, lucid said:

You mean it makes it easier for working on the implementation itself?   To use the implementation you should only need the one include in the main directory.

When I'm using the library, I only need the compiled and linked lib file and the header files. Currently the header files are mixed with the source files. So if I want to use them, I have to collect them from a dozen different folders. That's why in C/C++ one usually has a src folder with all the .c/.cpp files and an inc folder with all the .h/.hpp files. (The src and inc folders can have subfolders.)

Share this post


Link to post
Share on other sites
1 hour ago, Banbury said:

When I'm using the library, I only need the compiled and linked lib file and the header files. Currently the header files are mixed with the source files. So if I want to use them, I have to collect them from a dozen different folders. That's why in C/C++ one usually has a src folder with all the .c/.cpp files and an inc folder with all the .h/.hpp files. (The src and inc folders can have subfolders.)

Why do you need to collect the header files? You only need to set the include directory so the compiler finds them.

Share this post


Link to post
Share on other sites
17 hours ago, labsin said:

Why do you need to collect the header files? You only need to set the include directory so the compiler finds them.

For complicated reasons UE4 requires that plugins have to be recompiled every time they are packaged into a game. So game-makers need the libraries and their header files in the project or they couldn't use my plugin. Trust me, I know what I'm doing.

Share this post


Link to post
Share on other sites

After some time spent on a tricky bug, I definitely think that the setCurrentAnimation should stop any animation blending like this:

void EntityInstance::setCurrentAnimation(const std::string & animationName)
    {
        currentEntity->setCurrentAnimation(animationName, &currentAnimation);
        blendedAnimation = 0;
        blendCurrentTime = 0;
        blendTotalTime = 0;
        isPlaying = true;
    }

Otherwise it can happen that a call to it during an animation blending will just be ignored.

Share this post


Link to post
Share on other sites

@conceptgame @Banbury

Latest commit:

  • changed void EntityInstance::setCurrentAnimation(const std::string & animationName) to stop any current blends
  • fixed a bug where entities appended after creation would add all animations and objects to the new EntityInstanceData twice
  • added scale and alpha initialization to BoxObjectInfo constructor
  • added alpha to BoxObjectInfo::setObjectToLinear
  • added the following functions to EntityInstance:
    • std::string currentEntityName()
    • std::string currentAnimationName()
    • void appendEntity(SpriterModel * model, std::string entityName)
    • void setCurrentEntity(const std::string & newEntityName, const std::string & newAnimationName, SpriterModel * modelForAutoAppend)
    • UniversalObjectInstance *objectIfExistsInCurrentFrame(const std::string & objectName)
    • int animationCount()
    • bool animationJustFinished(bool orLooped = false)
    • void setCurrentTimeToPreviousKeyFrame()
    • void setCurrentTimeToNextKeyFrame()
    • void setCurrentTimeToKeyAtIndex(int newKeyIndex)
    • int currentMainlineKeyIndex()


       

@Banbury To get a points coordinates do:
 

UniversalObjectInterface *myPoint = objectIfExistsInCurrentFrame(pointName);
if(myPoint)
{
     int x = myPoint->getPosition().x;
}

 

Share this post


Link to post
Share on other sites

Thanks for the commit lucid.

I have implemented almost all of these changes in my current build.

I have found one other critical point though:

If the current animation is finished, there is no rendering anymore. That is weird since the position of the object can be changed or if there is a scrolling the display on the screen should be changed.

I have changed void EntityInstance::setTimeElapsed(real timeElapsed) so that it is not checking the isPlaying flag and it is working properly.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...