Jump to content
Spriter Forums

SpriterDotNet - An implementation for all C# frameworks


loodakrawa

Recommended Posts

On 12/1/2016 at 10:35 AM, AndyGFX said:

Hi, 

yes I tried included example for unity where is set next map from animator entity, but when I use for example 'no_weapon' on my animated character, then all sprites are invisible on character in scene. In Spriter editor when is changed available map to active, then is defined sprites are removed from actor in scene. Works this in code in same logic?

Second problem is, how can I set multiple maps items on character similar as is set in Sprites editor, when I want hide armor and weapon (drag and drop to column Active).

In doc missing information what is master map list and where is actual and how works map item  fields. I tried debug array from animator entity, I see all defined maps in character maps list in entity instance, but animator.characterMap is null and when is set to map from entity characterMaps , then doesn't works.

Maybe a few methods like SetMapActive(name) and SetMapInactive(name) would by nice to have and transparent from user point of view.

 

Best regards,

AndyGFX

I didn't understand your first question - could you rephrase it somehow?

As for the other issue - I didn't realise Character Maps can stack so I raised an issue and I'll try to fix it asap.

Link to comment
Share on other sites

Hi, I hope this is the right topic.

Last year, in March, I made some changes to Spriter2Unity (not Dengar's implementation, but bonus2113's) to make it work with 2DToolkit. However, a few months later, I decided to put my project on hold. I've just resumed (yeah, I'm a lazy guy, I'm usually super motivated for two months and then BAM - it's gone) and I would like to know if somebody is already working on a 2DTK plugin for your implementation? If not, and if I can understand how your implementation works (I haven't looked at it yet), I may try to do it myself. That would help me dust off my poor programming skills.

A lot has happened since I left and I'm happy to see the Spriter Team has successfully released its Reference Implementation.

Keep up the good work guys!

Link to comment
Share on other sites

5 hours ago, Wledig said:

Hi, I hope this is the right topic.

Last year, in March, I made some changes to Spriter2Unity (not Dengar's implementation, but bonus2113's) to make it work with 2DToolkit. However, a few months later, I decided to put my project on hold. I've just resumed (yeah, I'm a lazy guy, I'm usually super motivated for two months and then BAM - it's gone) and I would like to know if somebody is already working on a 2DTK plugin for your implementation? If not, and if I can understand how your implementation works (I haven't looked at it yet), I may try to do it myself. That would help me dust off my poor programming skills.

A lot has happened since I left and I'm happy to see the Spriter Team has successfully released its Reference Implementation.

Keep up the good work guys!

Hi,

As far as I know, no one is working on that ATM so feel free to do it if you feel like it. I suggest you take a look at the examples and github documentation and you should get a good understanding of how it works. Also, please read CONTRIBUTING.md before starting any work. If you have any questions, feel free to ask me here (or in the Unity plugin thread).

Cheers

Link to comment
Share on other sites

Hi! 

I'm having some difficulty hunting down an IndexOutOfRangeException Error, and are looking for some guidence.

I'm by far not a pro at C# and I've just recently started using SpriterDotNet for Unity and I've gotten it all to work. But I get this error on certain animations:

IndexOutOfRangeException: Array index is out of range.
(wrapper stelemref) object:stelemref (object,intptr,object)
SpriterDotNet.SpriterProcessor.GetBoneInfos (SpriterDotNet.SpriterMainlineKey key, SpriterDotNet.SpriterAnimation animation, Single targetTime, SpriterDotNet.SpriterSpatial parentInfo) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterProcessor.cs:316)
SpriterDotNet.SpriterProcessor.UpdateFrameData (SpriterDotNet.FrameData frameData, SpriterDotNet.SpriterAnimation animation, Single targetTime, SpriterDotNet.SpriterSpatial parentInfo) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterProcessor.cs:111)
SpriterDotNet.AnimationDataProvider.DefaultAnimationDataProvider.GetFrameData (Single time, Single deltaTime, Single factor, SpriterDotNet.SpriterAnimation first, SpriterDotNet.SpriterAnimation second) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/AnimationDataProvider/DefaultAnimationDataProvider.cs:19)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Animate (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:234)
SpriterDotNetUnity.UnitySpriterAnimator.Animate (Single deltaTime) (at Assets/SpriterDotNet/UnitySpriterAnimator.cs:44)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Step (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:226)
SpriterDotNetUnity.SpriterDotNetBehaviour.Awake () (at Assets/SpriterDotNet/SpriterDotNetBehaviour.cs:54)
UnityEngine.Object:Instantiate(GameObject)
BossManager:InstantiateBoss() (at Assets/Managers/BossManager.cs:105)
BossManager:NextBoss() (at Assets/Managers/BossManager.cs:77)

First of all I made a change in the SpriterDotNetBehaviour.cs and changed the Start function to Awake instead since I was getting null references when trying to listen to animator.AnimationFinished in the Start function of other scripts. So far I have not encounered any problems with this change (I still get the IndexOutOfRangeException when reversing this). Do you know of any further risks for having this in Awake instead of Start?

If anyone could point me in the right direction that would be awesome! :-)

Peace!

EDIT: I've seen others having trouble with negative widths. I have negative scaling (no negative widths) occuring, but I've tried to remove this aswell to no success . :'( 

Edited by Maisey
Link to comment
Share on other sites

Many thanks, Loodakrawa for the effort you have put into this project. I was able to successfully migrate our project, on Friday, and we are now happily using SpriterDotNet for our enemy animations. w00t!

I am now working on migrating over our player character which includes a bunch of customization options such as character cosmetics, equipped weapons, equipped armor, etc. Do you or anyone else on this thread have a best practices recommendation on how I should be finding and replacing these sprites in code using SpriterDotNet? 

Will the numbers assigned to a sprite element change if the .scml file is resaved?

Thanks,
James

Link to comment
Share on other sites

8 hours ago, Maisey said:

Hi! 

I'm having some difficulty hunting down an IndexOutOfRangeException Error, and are looking for some guidence.

I'm by far not a pro at C# and I've just recently started using SpriterDotNet for Unity and I've gotten it all to work. But I get this error on certain animations:

IndexOutOfRangeException: Array index is out of range.
(wrapper stelemref) object:stelemref (object,intptr,object)
SpriterDotNet.SpriterProcessor.GetBoneInfos (SpriterDotNet.SpriterMainlineKey key, SpriterDotNet.SpriterAnimation animation, Single targetTime, SpriterDotNet.SpriterSpatial parentInfo) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterProcessor.cs:316)
SpriterDotNet.SpriterProcessor.UpdateFrameData (SpriterDotNet.FrameData frameData, SpriterDotNet.SpriterAnimation animation, Single targetTime, SpriterDotNet.SpriterSpatial parentInfo) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterProcessor.cs:111)
SpriterDotNet.AnimationDataProvider.DefaultAnimationDataProvider.GetFrameData (Single time, Single deltaTime, Single factor, SpriterDotNet.SpriterAnimation first, SpriterDotNet.SpriterAnimation second) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/AnimationDataProvider/DefaultAnimationDataProvider.cs:19)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Animate (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:234)
SpriterDotNetUnity.UnitySpriterAnimator.Animate (Single deltaTime) (at Assets/SpriterDotNet/UnitySpriterAnimator.cs:44)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Step (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:226)
SpriterDotNetUnity.SpriterDotNetBehaviour.Awake () (at Assets/SpriterDotNet/SpriterDotNetBehaviour.cs:54)
UnityEngine.Object:Instantiate(GameObject)
BossManager:InstantiateBoss() (at Assets/Managers/BossManager.cs:105)
BossManager:NextBoss() (at Assets/Managers/BossManager.cs:77)

First of all I made a change in the SpriterDotNetBehaviour.cs and changed the Start function to Awake instead since I was getting null references when trying to listen to animator.AnimationFinished in the Start function of other scripts. So far I have not encounered any problems with this change (I still get the IndexOutOfRangeException when reversing this). Do you know of any further risks for having this in Awake instead of Start?

If anyone could point me in the right direction that would be awesome! :-)

Peace!

EDIT: I've seen others having trouble with negative widths. I have negative scaling (no negative widths) occuring, but I've tried to remove this aswell to no success . :'( 

Hi.

I think this is due to a bug I fixed after the version 1.2. I plan to make the next release in the next couple of days and that should take care of the exception you're getting. In the meantime, you can try checking out the dev branch from GitHub and trying with that.

I guess the Awake method should also be fine. I know I placed the init logic in Start and not Awake for some reason but I can't remember why. I'll take a look and move it there if possible since this causes problems for a number of people.

Link to comment
Share on other sites

6 hours ago, dementedangst said:

i would like to take advantage of the character map stacking in current dev branch of v1.3.0.,how can i go ahead and get started using it now instead of waiting for an official release.    

I'm going to create a release in a couple of days.

However, if you want to try it out before,  do this (assuming you're using Unity): check the dev branch from GitHub, build the SpriterDotNet.sln solution and replace the contents of the SpriterDotNet folder in your project with the contents of the SpriterDotNet.Unity\Assets\SpriterDotNet\ folder in the solution.

 

4 hours ago, Thrasher said:

Many thanks, Loodakrawa for the effort you have put into this project. I was able to successfully migrate our project, on Friday, and we are now happily using SpriterDotNet for our enemy animations. w00t!

I am now working on migrating over our player character which includes a bunch of customization options such as character cosmetics, equipped weapons, equipped armor, etc. Do you or anyone else on this thread have a best practices recommendation on how I should be finding and replacing these sprites in code using SpriterDotNet? 

Will the numbers assigned to a sprite element change if the .scml file is resaved?

Thanks,
James

Glad to hear you got it working!

The easiest way of swapping individual sprites is using the SwapSprite (and UnswapSprite) methods of the SpriterAnimator.

What do you mean by numbers assigned to a sprite element?

Link to comment
Share on other sites

2 hours ago, loodakrawa said:

The easiest way of swapping individual sprites is using the SwapSprite (and UnswapSprite) methods of the SpriterAnimator.

What do you mean by numbers assigned to a sprite element?

Thanks for the reply. In order to use SwapSprite I need to first find the original sprite (i.e. GameObject.Find("Sprite 5").GetComponent<SpriteRenderer>().sprite). Is there a more efficient way to reference the existing sprite from within SpriterDotNet (by name) to avoid making a GameObject.Find call? If not, is there any guarantee that this sprite will always be "Sprite 5" assuming the base asset in Spriter Pro is never removed or changed?

Thanks!

Link to comment
Share on other sites

9 hours ago, loodakrawa said:

Hi.

I think this is due to a bug I fixed after the version 1.2. I plan to make the next release in the next couple of days and that should take care of the exception you're getting. In the meantime, you can try checking out the dev branch from GitHub and trying with that.

I guess the Awake method should also be fine. I know I placed the init logic in Start and not Awake for some reason but I can't remember why. I'll take a look and move it there if possible since this causes problems for a number of people.

Alright!

Thanks Loodakrawa, you're the best! ^^

Link to comment
Share on other sites

16 hours ago, Thrasher said:

Thanks for the reply. In order to use SwapSprite I need to first find the original sprite (i.e. GameObject.Find("Sprite 5").GetComponent<SpriteRenderer>().sprite). Is there a more efficient way to reference the existing sprite from within SpriterDotNet (by name) to avoid making a GameObject.Find call? If not, is there any guarantee that this sprite will always be "Sprite 5" assuming the base asset in Spriter Pro is never removed or changed?

Thanks!

There is no guarantee. These game objects are just temporary containers for the library to fill with current sprites.

If you need a list of sprites, you can get them in the SpriterDotNetBehaviour.SpriteData field under FileEntries. Keep in mind that a file entry can have either Sprite or AudioClip reference set. Another important thing - the SpriteData is a ScriptableObject which means it is shared between ALL instances.

Link to comment
Share on other sites

Awesome! Thanks again. I had missed the FileEntries field. I am now able to successfully swap out all of my character customization assets.

The one thing remaining that I'm having some difficulty with is that the swapped sprite is using the sprite pivot from the original sprite. For example, if I swap hairstyle05 for hairstyle_default (which has a centered pivot of 0.5, 0.5) then the center of hairstyle05 will be on the center of hairstyle_default regardless of the pivot point set for hairstyle05. This becomes an issue anytime the swapped sprite is a different size than the default and I want to alight a non-center point with the center of the sprite being replaced. 

If I'm working in the Unity Editor and simply drag hairstyle05 onto the spriterenderer associated with hairstyle_default everything lines up just fine. However, when I swap these sprites using SwapSprite(hairstyle_default, hairstyle05) the new hair style is misaligned. Is there a way to have this function as it does natively in the Unity Editor? 

Thanks,
James

 

 

Link to comment
Share on other sites

15 hours ago, Thrasher said:

Awesome! Thanks again. I had missed the FileEntries field. I am now able to successfully swap out all of my character customization assets.

The one thing remaining that I'm having some difficulty with is that the swapped sprite is using the sprite pivot from the original sprite. For example, if I swap hairstyle05 for hairstyle_default (which has a centered pivot of 0.5, 0.5) then the center of hairstyle05 will be on the center of hairstyle_default regardless of the pivot point set for hairstyle05. This becomes an issue anytime the swapped sprite is a different size than the default and I want to alight a non-center point with the center of the sprite being replaced. 

If I'm working in the Unity Editor and simply drag hairstyle05 onto the spriterenderer associated with hairstyle_default everything lines up just fine. However, when I swap these sprites using SwapSprite(hairstyle_default, hairstyle05) the new hair style is misaligned. Is there a way to have this function as it does natively in the Unity Editor? 

Thanks,
James

 

 

All the positions are calculated based on the information in the .scml file. That means if you swap a sprite with another one, all the transformations still come from the original one. The replacement sprite is just drawn in place of the original one. If you need to swap sprites with ones of a different size at runtime you can probably achieve it by extending the UnitySpriterAnimator and overriding the ApplySpriterTransform method and doing all the custom logic in it.

Link to comment
Share on other sites

Hi,

@Loodakrawa 

First of all thanks for this implementation in C#. I am porting it to Haxe and already have it passing the tests. I am now in the process of streamlining it and optimizing it. I am also polishing the api and I have got a question regarding the boxData in the FrameData. It is set as a Dictionary with objectId (Int) as keys. 

Are we suposed to know the objectId to get the box information?

Would it not be better to get it via name ?

Or is there any reason why it is like this ?

 

Another thing that was bugging me is this issue : https://github.com/loodakrawa/SpriterDotNet/issues/41

it feels like a bug to me.

If not could you explain why it quits early ?

 

Thanks

 

Link to comment
Share on other sites

On 29/1/2016 at 3:20 PM, Tristan said:

Is there some way to simulate Spriter's pixel art mode using SpriterDotNet? The plugin works so smoothly, but my pixel art animations appear to be using Spriter's smooth sampling.

I wasn't aware of the existence of the pixel art mode. I'll investigate and try to make it working asap.

 

On 30/1/2016 at 1:39 AM, wighawag said:

Hi,

@Loodakrawa 

First of all thanks for this implementation in C#. I am porting it to Haxe and already have it passing the tests. I am now in the process of streamlining it and optimizing it. I am also polishing the api and I have got a question regarding the boxData in the FrameData. It is set as a Dictionary with objectId (Int) as keys. 

Are we suposed to know the objectId to get the box information?

Would it not be better to get it via name ?

Or is there any reason why it is like this ?

 

Another thing that was bugging me is this issue : https://github.com/loodakrawa/SpriterDotNet/issues/41

it feels like a bug to me.

If not could you explain why it quits early ?

 

Thanks

 

Hi!

I'm using the id (id == array index in almost all the cases) because I load all the data from the .scml to arrays. I think having the string as key should be pretty much the same (I'm just not sure if all the ObjectInfos in the .scml MUST have a name set) if you have a slightly different data structure. In the end I'm passing the whole ObjectInfo in the processing method.

I didn't have a chance to take a look at the issue you reported but at first glance it does seem like a bug. I'll investigate it asap.

Fun fact - my first Spriter implementation was done in Haxe a while ago (although it was significantly different that this one)

Cheers

Link to comment
Share on other sites

Thanks for the info,

I saw the use of box in the processing method but I thought about box as collision box and thus do not plan to actually draw them. They seemed to me more useful as data to be probed hence the use of name as key. On that note, I am not sure Spriter enforce the absence of duplicated name? I ll have to check that

Haxe is pretty cool, my version should work on c# too :)

 

 

Link to comment
Share on other sites

11 hours ago, wighawag said:

Thanks for the info,

I saw the use of box in the processing method but I thought about box as collision box and thus do not plan to actually draw them. They seemed to me more useful as data to be probed hence the use of name as key. On that note, I am not sure Spriter enforce the absence of duplicated name? I ll have to check that

Haxe is pretty cool, my version should work on c# too :)

 

 

Box is supposed to be for collisions. It is up to the derived classes to do something with the ApplyBoxTransform method - not necessarily draw the box. For example, In the Monogame example I'm drawing the boxes because there's nothing better I can do but in the Unity examples, the box is mapped to the native Unity collider and all transforms get applied in the ApplyBoxTransform method. So in other words, that method gets called every frame for each box with the calculated spatial data for it and it's up to the actual implementation to do something meaningful with it.

Link to comment
Share on other sites

  • 2 weeks later...

Hi @loodakrawa,

Thank you for creating SpriterDotNet.

I've seen people getting similar errors, here is the one I'm getting (I'm using develop branch)

IndexOutOfRangeException: Array index is out of range.
SpriterDotNet.SpriterProcessor.UpdateFrameData (SpriterDotNet.FrameData frameData, SpriterDotNet.SpriterAnimation first, SpriterDotNet.SpriterAnimation second, Single targetTime, Single factor) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterProcessor.cs:48)
SpriterDotNet.AnimationDataProvider.DefaultAnimationDataProvider.GetFrameData (Single time, Single deltaTime, Single factor, SpriterDotNet.SpriterAnimation first, SpriterDotNet.SpriterAnimation second) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/AnimationDataProvider/DefaultAnimationDataProvider.cs:23)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Animate (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:234)
SpriterDotNetUnity.UnitySpriterAnimator.Animate (Single deltaTime) (at Assets/SpriterDotNet/UnitySpriterAnimator.cs:44)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Step (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:226)
SpriterDotNetUnity.SpriterDotNetBehaviour.Update () (at Assets/SpriterDotNet/SpriterDotNetBehaviour.cs:66)

Any help/suggestions would be much appreciated

Link to comment
Share on other sites

9 hours ago, davomcdavo said:

Hi @loodakrawa,

Thank you for creating SpriterDotNet.

I've seen people getting similar errors, here is the one I'm getting (I'm using develop branch)

IndexOutOfRangeException: Array index is out of range.
SpriterDotNet.SpriterProcessor.UpdateFrameData (SpriterDotNet.FrameData frameData, SpriterDotNet.SpriterAnimation first, SpriterDotNet.SpriterAnimation second, Single targetTime, Single factor) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterProcessor.cs:48)
SpriterDotNet.AnimationDataProvider.DefaultAnimationDataProvider.GetFrameData (Single time, Single deltaTime, Single factor, SpriterDotNet.SpriterAnimation first, SpriterDotNet.SpriterAnimation second) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/AnimationDataProvider/DefaultAnimationDataProvider.cs:23)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Animate (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:234)
SpriterDotNetUnity.UnitySpriterAnimator.Animate (Single deltaTime) (at Assets/SpriterDotNet/UnitySpriterAnimator.cs:44)
SpriterDotNet.SpriterAnimator`2[TSprite,TSound].Step (Single deltaTime) (at C:/dev/libs/SpriterDotNet/SpriterDotNet/SpriterAnimator.cs:226)
SpriterDotNetUnity.SpriterDotNetBehaviour.Update () (at Assets/SpriterDotNet/SpriterDotNetBehaviour.cs:66)

Any help/suggestions would be much appreciated

Hi, are you perhaps trying to blend two animations with a different hierarchy? More about it here. If not, can you please upload your .scml somewhere so I can investigate this further.

Link to comment
Share on other sites

  • 3 weeks later...

Hey Loodakrawa, 

Would you prefer feedback discussion in this thread or in the SpriterDotNet github repository?  

I have a question regarding creating Spriter Entities/Animations with Monogame.  It's possible that the feature/monogame branch is just in flight but it looks like every time a new Animator gets created it is required that all of the associated assets (sounds and images) have to be registered with the animator.  This seems like a lot of unnecessary looping in the scenario where lots of animations are being potentially created.  i.e. every time a new animation gets turned on (even if if is the same as others in the current scene) we are going through the process of creating the collection of collections in SpriterAnimation that holds the mapping between the folder/file path and the asset itself.  Wouldn't it make more sense to create this mapping once per scml/SpriteEntity and then associate the SpriterAnimation with the appropriate mapping?

Forgive me if I'm missing something as I'm very new to Spriter and the Spriter API.

Thanks in advance and thanks for all the work you're doing on this implementation!

Edit: I believe what I'm describing is the flyweight implementation that @lucid leverages in the C++ implementation.  With factories that are responsible for instantiating entity instances: 

  • EntityInstance *entityInstance = scmlModel.getNewEntityInstance(entityName or entityIndex);

I may try to see if I can't take a swag at something like this in my fork.

Edited by jonathanpmast
more details
Link to comment
Share on other sites

22 hours ago, jonathanpmast said:

Hey Loodakrawa, 

Would you prefer feedback discussion in this thread or in the SpriterDotNet github repository?  

I have a question regarding creating Spriter Entities/Animations with Monogame.  It's possible that the feature/monogame branch is just in flight but it looks like every time a new Animator gets created it is required that all of the associated assets (sounds and images) have to be registered with the animator.  This seems like a lot of unnecessary looping in the scenario where lots of animations are being potentially created.  i.e. every time a new animation gets turned on (even if if is the same as others in the current scene) we are going through the process of creating the collection of collections in SpriterAnimation that holds the mapping between the folder/file path and the asset itself.  Wouldn't it make more sense to create this mapping once per scml/SpriteEntity and then associate the SpriterAnimation with the appropriate mapping?

Forgive me if I'm missing something as I'm very new to Spriter and the Spriter API.

Thanks in advance and thanks for all the work you're doing on this implementation!

Edit: I believe what I'm describing is the flyweight implementation that @lucid leverages in the C++ implementation.  With factories that are responsible for instantiating entity instances: 

  • EntityInstance *entityInstance = scmlModel.getNewEntityInstance(entityName or entityIndex);

I may try to see if I can't take a swag at something like this in my fork.

Hey,

I prefer discussions here and bug reports / feature requests as issues on GItHub.

You are right - it doesn't make much sense to have the same mapping per SpriterAnimator when it can easily be per shared. I opened a GitHub issue for this.

Regarding the MonoGame example - I'm fixing the MonoGame plugin to be more like an actual plugin and not just a simple example.

Link to comment
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...