 At least that mostly kind of almost just kind of works. Hi. If you're here for another talk, this will be very exciting for you because this is not that talk. This is this talk. This is we're talking about Swiffle, which is getting grease pencil into some of the more traditional 2D animation pipelines. And really what that's talking about is IO. It's really talking about getting vector data from other places into Blender and hopefully from Blender into other places. Also, I'm going to start off by also saying, I talk quickly. I try to talk slower than normal, but I speak quickly. And so if anything doesn't make sense or if I'm speaking too quickly, either watch it later and watch it slower or just raise your hand and say, slow down or ask me what I'm talking about. I don't mind interruptions. It actually helps me figure out what I'm supposed to be saying next. So speaking of which, I'll give myself a little quick introduction of myself. I am that guy, Jason Van Gumpster. I work with Orange Turbine, which is under the loving umbrella of CG Cookie, focusing predominantly on consultation for getting Blender working better in studio pipelines for studios as well as toolmakers. So that's really what my focus is. I also wrote Blender for Dummies. I'm lead moderator on Blender Artist. I also started Right Click Select. So sorry, and you're welcome. And for a brief, not too brief period, I was running a small podcast called The Open Source Creative Podcast. I don't think I've recorded an episode in a couple of years. So maybe it might be faded just a touch. And then that's me if you want to follow me on any of the social media stuff. So what is Swiffle? In short, Swiffle is an add-on for Blender for getting SWF into grease pencil. Yeah, I heard laughs. That's right. Yeah, in fact, what year is it? So for those of you who maybe didn't suffer through the internet in the 90s and early aughts, SWF is the output format for Flash, formerly Macromedia Flash, now Adobe Flash, now Adobe Animate. It's a binary format, but here's what it comes down to. For 2D animation, there aren't very many options for data interchange. There's not really, I mean, you have SVG, but from an animation standpoint, none of the animation applications really support it very well for keyframming and those sort of things. Even the reference standard, which is Inkscape, doesn't really do animation very well on its own either. So you don't really have, if you're working in Adobe Animate or you're still working in Flash and you want to work in grease pencil or you want to work in Toon Boom, I mean, I've never talked about that. SVG, not it. And SWF is pretty much, SWF is pretty much what's it. Image sequences, you could use image sequences, but we want the vector data, right? We want to be able to take the drawing and sculpt it and modify it and change it and actually be able to maintain some level of workflow and have some data fidelity from one application to another. It'd be nice. It'd be great. We don't have even really the same thing as OBJ or FBX or Alembic or USD. It doesn't exist for 2D. It's just not there. The unfortunate truth is that SWF is really what is it. That's what exists. So that's what we have to work with. And so there are good things. There is actually some really, really interesting and good things about that. So the good news is that the spec is most mostly open. There is a, I have to make sure that I have my notes in here. Yeah, good. All right, so there is a published-ish PDF specification that it was on the Adobe website. I can't seem to find it anymore, but fortunately I downloaded it. So it does describe at least up to SWF version 9, I think. So at least we're backwards compatible, right? So we've got that. I've been able to talk to the developers and engineers at the Adobe Animate team. They like Blender. They love Blender. But they really want to show that there's a use case for people who are doing interchange between Blender and an application like Animate. So they'll give me feedback. They've been able to share with me some test files and those sorts of things. So that's been nice. But they won't write the code for me, which as somebody who's not really a developer, that's a little disappointing. And there is actually an existing Python library, PySWF. I think the last commit to it was about eight years ago. But it does support Python 3, at least the version that's on GitHub. I don't think he actually ever released the Python 3 version. So if you just pull it from GitHub, great. There's some complications with that, though. Some of them, it's partially dealing with libraries and dependencies and how Blender interacts with it. So that was the good stuff. This is where we start with good. Yes. So that, yeah, like really, I mean, like I said, this library that I'm using was the last commit, was about eight years ago. And it's not maintained. I sent an email to the developer a year ago. And if you happen to watch this on anything, please email me back. I really appreciate it. Also, more technically, SOF is a binary format. So you're storing data in a way that there's not an API, really, unless you use this library or you write your own parser for it, or you read the actual spec and you're really good at sort of figuring out that this little binary string means this and this little binary string means that. And then we can sort of make them play together and do the great things and have fun with it. It's small and it's efficient as a format. It's great for delivering content. It is not meant to be an interchange format, but we don't care because there's nothing else. And so also, there's novel approaches to storing vector data. It's very clever. You ever run into a person who has a very, very interesting way of doing things? And you look and you say, that is so brilliant for you. That's SWF. There's really interesting. For instance, a stroke in SWF has three different bits of color data. There's a chunk of color data that is the actual color of the stroke. That makes sense. That's great. There's another chunk of data for what we'll call the inside of the stroke. And then there's another color for the outside of the stroke, even if the stroke is not closed. And if strokes start overlapping, then that's when the inside and outside starts to kind of make sense. But it really depends on whether or not it's a clockwise stroke or a counterclockwise stroke. The library helps with that, but I can understand what the library is doing. So then we get to the ugly. And the ugly is really, this is part of the part that deals with the blinder, sadly. One of the biggest things here is that I'm using a Python module. The Python module is in pip, but because it's so old and because I really need to sort of abuse it in a way that probably wasn't designed to abuse, because it does spit out SVG kind of nicely, but it doesn't do the animation part quite the way I want. I have to use it. If you ever have, has anybody done actual Python development here at all? Because I'm not going to raise my hand. The functions that start with underscores, conventionally those are the please don't use these functions. I'm using those functions. And so what I've actually done is I've pulled that library into the Swifl add-on just so I can access those things and make it accessible to me. But even then, that PySWF library requires libxml and the LZMA for compression. Those don't come with Blender's Python. And if anybody's tried to load an external module to make it work with Blender's Python, it's fraught with challenges, we'll say. It is not... I have thoughts. I have opinions. What it comes down to is that we don't have a mechanism for that. That's really nice. The whole system, Blender's Python is sandboxed to Blender kind of like a virtual environment, which is great. It was made before virtual environments and VMs and those sort of things became sort of a mainstay within Python development. And now the problem is that because it's different, we either have the choice of abandoning where Blender's sandbox Python is and trying to adopt something like a VM or re-implementing all of PIP and Blender. Neither one of those are easy. So it's not easy to solve, but also not friendly for somebody who just wants to get pretty images into Blender. The other one is, well, back to the old comment of it, being very old. It's really challenging to find good examples of test files, especially ones that don't involve ActionScript. Some of these, if you want to talk to a studio that's doing it, they might share files, but they're studios. They don't... Once there's still stuff in work and development, they also have these large dependencies. They're not going to build you necessarily a good test file. So it's hard to find that sort of thing. Fortunately, I had a couple of really good resources and references for that, but it took a second to do that. Also, testing those files, you might have noticed that I work in Linux predominantly. Finding ways to even just view an SWF file in Linux is there's some research involved just with that part of it. I found a really cool tool for that called Ruffle, which is written in Rust. So there's nice. And the ugliest part about this is something that I'm still struggling with with the add-on. It's z-ordering issues. And it's really... I've said this a number of times to anybody who's asked. This is where I believe I've run up to the limits of my competence. And hopefully somebody here can push beyond those limits and help me out a little bit later. So if we do, please talk to me about that, because that'd be fantastic. All right. That said, the add-on actually works. We have things that behave and do really cool things. And so I'm gonna give a little bit of a demo right here. And hopefully the resolution and things changing doesn't blow up everything in the world here. So this is a... I'm using, I said, an application called Ruffle for viewing the SWF file. This is my reference. And it comes from a book called To Digital Animates CC by Stephen Brooks. And he very kindly gave me permission to use this for testing. And I'm gonna say abuse. So Ruffle doesn't like some of these things. Sure, I guess I'm hungry, but I don't know. What do you want to eat? I'm not sure, I guess I'm hungry, but... It's gonna loop. I don't know, what do you want to eat? There we go. Sure, I guess I'm hungry, but I don't know. What do you want to eat? Let that go two more times. Sure, I guess I'm hungry, but I don't know. What do you want to eat? All right. Sure, I guess I'm hungry. All right, so I have to say it three times. So that's my reference. It's a character animation. There's frame replacement. There's drawing that's being changed and manipulated. I want that in Blender as grease pencil objects with the audio so that I can change it and do stuff later. And this is where everything should probably break on me. So good old Blender launch. And why is it doing it that way? I don't know, full screen. Window, window. All right, so what you can do is we're gonna do a new, and we're gonna do a 2D animation. And we have our handy little 2D animation. I could go back into object mode, but I'm not going to. File, so actually let's do this real quick. Assuming that nobody has installed it. Here's where I was talking about one of the weird things about the sat-on is that it requires some external modules. And I was able to find some really friendly code that was shared for me on that. If we go to add-ons here and I type in Swiffle testing, I know it's enabled. Ah, I didn't call it Swiffle here. That's my fault. So, one of the things about this add-on is that it requires pillow for image manipulation because it needs to pull in textures for textures and images. The other thing it requires is libxml because the PySWF library sort of tries to use SVG or some SVG-esque structure as an intermediary and I haven't figured out how to yank that out yet of the code. And then Piles in A, which is for compression. All of these things are, they're modules on PIP you can get, but they're also optimized and need to be compiled for whatever operating system you're on because it compiles it down to Python's, to C from Python, so it can be executed, which means just sort of pulling in these libraries like I did PySWF, it doesn't work and it's not multi-platform. So, you have to have this mechanism where if you don't have these things installed, this button, hypothetically, and it works for me, so it should work for you, this button allows you, will automatically install these dependencies against Python's, against Blender's Python. And it works, it should work, it's happy. And so we get these additions in here. And there's one of the other things that I forgot to mention in The Ugly. You've all worked with Res Pencil before, right? Yes, most of you, half of you? Okay, so, do you know how textures are mapped in Res Pencil? It's janky, oh, it's so janky. It's UV maps, which is great because just like curves, UV maps come with it for free, but the orientation of said UV map is based on the position and orientation of the first two points in the stroke. Which could be here, or here, or here, or here. And then in order to maintain that orientation, it goes about three quarters of the way around the stroke and then uses that as a secondary location. So if that point also moves, things flip and jump and do all sorts of crazy things. So it's not excessively predictable. And one of the things I would really, I'm looking forward to the, being able to have EV materials as part of Res Pencil, which is in the works to happen really soon now, which could be now or in the next five years, but it's gonna happen. But the mapping question is still one of those things that is I just love to have straight up, like projection mapping would make my life so much easier just from an inputting standpoint. That's one of the things that actually kind of works sane on SWF that Blender is a little insane about. So that's one of the other parts of that. But anyway, I digress. These are our dependencies, and this is the fun and exciting way that we get these dependencies into Blender's Python so that Swiffle can understand it and play with it. Once we do that, close that window. Then we go, all right, file, import, moment of truth. I'm gonna go and find that handy dandy little finger tapping SWF. Give it a second. Ah, I should have said that was the other part, right? Good news is all of the data is actually there. If I select any part of this tab and just go into edit mode, it's all there. And it's all the sound and everything is there. The problem is, what I was saying earlier, z-ordering. If I go through and take the time to put everything in the right order, which I have already done, so this is gonna be like a baking show. I'm going to not save this chaos. You end up with that. And if I play it. Well, sure, I guess I'm hungry, but I don't know. What do you want? Well, sure, I guess I'm hungry, but I don't know. What do you want to eat? Well, sure, I guess I'm hungry, but I don't know. And it's a lot easier to stop this on Blender than in Ruffle. So we have all of our keyframes. We have our audio imported. We have, let's zoom. It's really hard to do this without a touchpad. So I won't. So all of the keyframes, all the layers, one of the other really cool thing is, originally when I wrote this add-on, it was taking every drawing object that's stored in the SWF file and making it an actual grease pencil object. It works, but the problem is that when you deal with Z-ordering there, you basically have to move things in the actual Z-axis to make them play nice, which is gonna make exporting back out horrid. Fortunately, grease pencil objects already have layers and cool things built into them. And so because SWF is a binary format, I don't have layer names, unless they explicitly name them or use instances. And actually, if you have worked with Adobe Animate and you're used to working with, oh, now I forgot the actual term that they use, basically it's an encapsulated animation in its own setup. And it's a name that has nothing to do with animation. It's like symbol. Somebody said it, that's right, it's symbol. What the hell is a symbol for animation? That doesn't make any sense. Flash people. In any case, a symbol is basically a collection or an instance and we can be able to take advantage of that and play with that. So downside is I don't have really cool and clever naming. Upside is I still have them individually and I can turn things off and on, which that one actually didn't make any sense to do. Actually, I'm gonna find, that's the other one because it's not named. I can't tell you which layers do. Oh, I'm not even clicking the eyeball either. That's probably a, there we go, missing a finger. That's actually a little disturbing. So, but we have all of this information here. All of our materials are set in. I can get gradients and I can get textures. I can get them into Blender, but the challenge of getting them oriented correctly. I will show you a quick other example here. I'm gonna say I'm like a new file because sometimes things break. Don't save. And we're gonna go to this one. So this one, his nose is not supposed to be black. There's a gradient that runs from here up to give him sort of this reddish nose thing. This is actually an image texture of kind of like burlap and it's been color mapped and changed to fit into that, but it's actually not oriented properly and not the right scale. These are the problems that I was referring to when it comes to the way that texture mapping, the UV coordinates, particularly with grease missile objects work, it's hard to really predict which way is up, which way is going. So I have the image in and it might be oriented or rotated within the SWF file, but matching that with what predictably matching that with whatever is going on with a grease missile object is not trivial to use a good math professor terminology. So actually I can show you what this is supposed to look like as well. That probably helps make things make a little bit more sense. If I close Blender really quickly, actually, no, I don't need to do that. 10 completed. This one doesn't have audio, so you're not gonna get super annoyed by this one. Mostly. Completed SWF. I ruffled, don't complain. Come on, I miss my mouse. All right, so that's what he's supposed to look like and we can actually get, like I said, I have the gradient information that's in Blender. I have the hair texture, I have the gradient for the hair. That's all there. It's just not positioned properly. And so that's one of the challenges that we run into not just, I thought that all of the problem that I was gonna run into was gonna be on the SWF side. Turns out that eight year old library, really handy when I know how to use it, but you run into some issues because grease pencil as its original intent was never really originally designed to be used the way that we're using it now. And so there's some, there's some, we'll say we'll call it technical debt. There's some growing pains. There's some challenges with trying to get some of these things to work in a nice way for interchange, particularly things with respect to textures. But, I mean, like I said, all the data's there. It just needs to be coordinated and organized in a way that makes a modicum of sense. And now this is lower. Oh, I can make this higher. All right, so that was a little demo. So it works, at least on the import side of things. Yay! Now, as you might have noticed, it's still early days. I've been working on this add-on sort of whenever I have free time amongst the other fun, exciting things that I've been doing. So I work on it until I run into something that makes me want to rip my hair out. I haven't ripped out very much recently, so. But, nice-contained self-contained test files, they're going to difficult to come by. So I really, again, I want to thank Steven Brooks, who's rubber onion, basically everywhere. He actually has a podcast as well, so check him out. And his book is quite helpful. His files are actually online and available for downloading, but they're not creative commons. So if you want to monkey around with them, definitely contact them and ask for permission. The exporter part of this, hypothetically, should be easier because whatever is already in grease pencil, I can probably get out to SWF with some reasonable sense. There's going to be some challenges with trying to figure out how to flatten out the actual Z from that, but doing that from the camera view, probably, I think that's going to work out pretty well. I have the scaffolding in place for that to happen. And it's really just a matter of testing it, breaking it, testing it, breaking it, crying, testing it, and then getting it to work once and then trying to figure out how I got that to work. I believe that's the proper process for software development. Oh, also Stack Exchange. Lots, lots and lots of Stack Exchange that is actually, I think Stack Exchange happened after SWF, so that's not really useful at all. Best really for just be not understanding different things in Python. Yay! And I have bugs, so many bugs. And one of the things I just realized at this moment is that I didn't put a link on my slide. I'll have to show that in a second. Because as of right now, until I'm either too embarrassed by it or not, the whole of the source code for SWF as it currently stands is available on GitHub. And I'm gonna see if I can find it really quickly. Actually, I'm in a browser now. That's where I'm presenting. So let's do that. So, get, ooh, caps lock. GitHub.com slash, I'm pretty sure it's me. No? Nope, it's CG Cookie, isn't it? Yes, there it is. Sorry, yeah, sorry. GitHub.com slash CG Cookie slash SWFL. That is where this currently lives. And if you really wanna have some entertainment because I haven't really filtered myself when doing commits, the commit messages, they're real exciting. In fact, even the bug reports that I write to myself are very, very, very fun. And then you'll see me rambling to myself about why things aren't working and all the fun things that I tried. So this is the moment of that talk where it's my cry for help. If anybody actually wants to really help me with this, especially on this Z-order is wrong, wrong, wrong, I'm, please help me. This is one of the things, all the data's there. It's really about making sure that things are in the right order and it's really, like I said, has to do with things going counterclockwise and clockwise directions in the right way. And I think that that's gonna be one of those things that'll be really nice once it works. Because again, as an artist, if I have the time, I could actually get the data in now from an SOVF project, pull it into Blender, and once I monkey around with the layers and get it all working, assuming it's not like a three-minute shot, then I can start working with that grease missile data today and be just as happy. Of course, trying to get that out, I got the exporter to work, but that's where we are. So, where did my talk go? Oh, I'm still in Firefox. That's why. Alt-Tab? Nope, Control-Tab. Ah, I swear, I know how to use a computer. In any case, yes, this is early access. This is going on GitHub and trying to play with it. Definitely come contact me if you want to help. I'll be the hairy guy floating around that. I'm pretty loud. You can probably find me. Otherwise, I'll be down by the CG Cookie table and making a nuisance of myself there. Now, anybody have any questions? Yes. Which files? I don't know about Lottie Files. Tell me more. Okay. Okay, I'll have to look into that. One of the first suggestions I had when I talked to the engineers from Adobe Animate about what could I even use for interchange, their suggestion was, you know what, Animate does GLTF exports, their image is on plans. So, I'll have to look into that and see what that might make things, that'd be really nice if I can see it. That would make my life a lot easier because JSON plays nice with Python and everything else. So, definitely, I'm gonna have to figure out how to spell that, but track me down afterwards and we'll get that working out. Yes. From, from, from, so they are, they have a few different things. You can have straight lines, you can have interpolated lines, strokes and curves. And those are your two main sets and they can kind of be open and closed with that sort of clockwise, counterclockwise madness. So, grease pencil are not interpolated, actually. They're just a bunch of little steps. So, you actually have to, when you import from SWF, you actually have to interpolate and create all those points. They're bezier-ish. Okay, cool. Yeah, I'd love to play with that, that'd be really fun because, yeah, smacking my face against this is exciting. It's not. Yes! Okay, cool, yeah, once, cool. It means that I have to redo all of this, but I hear the second time you do anything, it's faster. So, that, I'm actually really, yeah, definitely track me down after this because I really want to find out more about this. I've been banging my head against this for, for a second. So, it'd be really nice to not have to do that as hard. So, cool. Anybody else have thoughts, questions, insults? Sweet, well, that's, that's pretty much it for my talk. I appreciate you guys hanging out and have a good conference.