Homeā€ŗ Coding, Scripting, Shaders

Tech Artist - What are you working on: FOREVER Edition!

1181921232456

Replies

  • Denny
    Options
    Offline / Send Message
    Denny polycounter lvl 14
    A rig of locators which the user use to setpositions and proportionsbefore generating the final rig. :)
  • Froyok
    Options
    Offline / Send Message
    Froyok greentooth
    Denny wrote: Ā»
    A rig of locators which the user use to setpositions and proportionsbefore generating the final rig. :)
    Ha ! I see !
    I saw some builders which allow you to do that but I'm not comfortable with this idea because based on what I want to do (allow the user to make joints where he wants and how many he wants) it will not be be compatible.

    (Maybe I'm wrong, I do this like an exercise after all ! :))
  • Denny
    Options
    Offline / Send Message
    Denny polycounter lvl 14
    Froyok >> Whatever you choose I bet it will turn out awesome. :)


    [ame="http://www.youtube.com/watch?v=LE4BcF7E0lo"]MirrorTable 1.6 - Automatic Generation.mp4 - YouTube[/ame]
    I finally managed to automate my MirrorTable script close to perfection! The script is incredibly bloated at 5121 lines now and needs spring cleaning, some small minor features has broken in the process, but the main purpose of the script is working awesome now! :D

    In the video above I demonstrate the script with five public rigs in 10 minutes. :)
  • r_fletch_r
    Options
    Offline / Send Message
    r_fletch_r polycounter lvl 9
    So, I was looking at scriptspot and found a peculiar experimental feature in Max 2012's Nitrous Viewport that I didn't know existed. Realtime Reflections!
    inGW7BcPcPCUM.gif

    Found about it on this script's page.



    Now get this to run at higher than 6 FPS on a machine like mine and ship it in the next cryengine update. :poly124:

    EDIT: on second thought, it's less special than I thought. On further inspection, It lookst like they are Live RTTing a cube map at the objects pivot for the reflections. Only really works well with spheres. Nothing special, cryengine already has something similar, still interesting though! :thumbup:
    still cool though.
  • Denny
    Options
    Offline / Send Message
    Denny polycounter lvl 14
    A friend of mine uses a different workflow for defining animations in a scene with nodes, I thought it sounded like a good idea so I rewrote my Axtended script to be a lot simpler. Both UI wise and code wise.

    exporter.gif
  • UnlimitedBacon
    7095511307_a90f455104_b.jpg

    Boom, basemesh.

    ....ihavenoideawhatimdoing.jpg

    EDIT: I think I came to the wrong neighborhood....oh gods this is embarrassing.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    might post here as well

    its a Bitmap Font tool (*.fnt) where you can design a font in Photoshop or any other tool and then generate a bitmap font from that.
    ShoeBox thread

    7093512575_dd3c739633_o.jpg
  • mLichy
    Options
    Offline / Send Message
    I've put up my bitmapResourcer to download on my site.

    http://www.matthewlichy.com/bitmapResourcer.html

    Let me know if you find any bugs. I should have fixed them all..... I hope...

    bitmapResourcer.jpg
  • Denny
    Options
    Offline / Send Message
    Denny polycounter lvl 14
    After some testing I have some feedback, I think the tool is awesome. Tested on Windows 8 x64 Consumer Preview without issues. :)

    * UI is very responsive, caches images very quickly and is easy to understand
    * The ImageSets feature is awesome. Some requests I have about it is that after you type a name using enter could create the image set. It would also be nice if double clicking an Image Set made it active.
    * I love the alpha preview feature.

    Some extra features I'd like to see is, and some bug reports;
    * Ctrl+Scroll to zoom in/out
    * Pressing alt activates what I believe is the same menus that is in an ordinary window. It locks scrolling and some other things until you click the mouse or alt again.
    * Some larger preview function would be nice, maybe holding a toggle button like alt to enlarge the image to window size if you're hovering above a thumbnail and go back to normal on release?
    * Drag and drop to image sets
    * Maybe a backward/forward button (side mouse buttons) for jumping between paths and image sets you've activated

    Love the tool, it's definitely useful. :)
  • mLichy
    Options
    Offline / Send Message
    Awesome, thank you :)

    Actually almost everything you mentioned I've thought about doing, besides the last thing.
    I think I could do all of that easily enough though.

    The Hover Preview/Enlarge is one I thought about a couple times. That should be easy enough to do I think...

    Not sure if Drag/Drop to imageSets will be easy enough, but it should be. I've done Drag/Drop before, in C#, but not WPF, but it should be similar.
  • LoTekK
    Options
    Offline / Send Message
    LoTekK polycounter lvl 17
    Not sure what happened, though it might be the fact that it defaults to "search subdirectories". I loaded up my ref folder (which has a shit ton of subdirectories with a shit ton of images), and it got progressively more sluggish as it generated/loaded thumbnails. It was less than 200 images in when things got so sluggish that it took me another 5 minutes just to pull up the Task Manager, and another 5 just to kill the task. At that point:

    bitmapResourcer.jpg

    Running the 64-bit version on Win7 64 with 8gb of ram.
  • mLichy
    Options
    Offline / Send Message
    Hmm... shit. Yeah, when you initially load images, it has to create the cache. If you reloaded that same folder/subfolder again, alot of them would be cached, and would load faster/use alot less ram.

    I think there might be an issue with the source image not getting let go from Memory on Load... But the Cached images are managed alot better. I def. need to look into this. : \

    Were those images large in size, like 20MB or even 200MB? I've loaded > 200 images without much usage/issue, but most of them were JPG or PNG.
  • LoTekK
    Options
    Offline / Send Message
    LoTekK polycounter lvl 17
    Were those images large in size, like 20MB or even 200MB?
    Hmm, not particularly. Mostly just jpgs, though there are a handful (less than 10) of large video files as well.
  • mLichy
    Options
    Offline / Send Message
    Yeah, Video files will eat up ram for sure, or can. But shouldn't be too bad.... Either way, I need to get that sorted if at all possible.

    On a side note:

    New Fixes I got working on my Machine:

    - Arrow Up/Down now goes up/down the ImageSet List.
    - Enter key now works to Add a new ImageSet.
    - Enter Key or Double Click on an ImageSet to Load it. (Enter key only works if a Textbox is not active.)
    - Drag with Left Mouse + C Key to add selected Images to an ImageSet.
    - Z Key held with mouse over a Thumb shows an enlarged Image. (Need to fix positioning yet).
  • mLichy
    Options
    Offline / Send Message
    Figured it out :) Got my FreeImage setup so it unloads the bitmaps properly as it creates the cache. So Ram usage goes up for each image, but as the image is converted to a thumbnail, it gets removed from Ram. So ram usage should be nice and low now in the end :).

    Also, I think by changing some things, it seems like images load even faster now, and maybe uses less ram :).

    I also fixed HDR Images, so now they load/look proper :D


    Edit: Just tested, I loaded 415 random images, mainly JPG, PNG, PSD, GIF and some AVIs. My Ram usage got only up to 220MB at its highest, and that was when it was finally all done. Otherwise, it stayed around 90-150MB :D
  • mLichy
    Options
    Offline / Send Message
    Alright, I updated the webpage/downloads. Check it out and let me know what happens :).

    I want to/need to fix up the Scaled Image position yet, and Id also like to sharpen the image somehow.

    http://www.matthewlichy.com/bitmapResourcer.html
  • AlexLeighton
    Options
    Offline / Send Message
    Hmm, the program is crashing whenever I try to load certain directories.. It's just folders full of a couple .tgas.
  • mLichy
    Options
    Offline / Send Message
    Hmmmm....Can u post a screenshot of the folder with the files in it? I feel maybe it's a naming issue.

    Or, I somehow put 32 bit files in x64. Or are u running the 32 bit version?

    Thanks!
  • animax
    Options
    Offline / Send Message
    animax polycounter lvl 15
    @mLichy - Same here.It crashes for me too but only for x64 version.32 bit version works like charm :)
  • Denny
    Options
    Offline / Send Message
    Denny polycounter lvl 14
    Getting better. The caching slowed down a bit after the update but I can live with it, better than filling the RAM.

    The drag and drop doesn't seem to be working well at all though. I've been spending a couple of minutes trying to get it to work and the only time I manage to is when default is not selected and then only default is droppable. Otherwise I can't drop to any image set at all. This is on x64.

    Also it seems double click doesn't register for me for loading an image set, enter works fine. :)
  • Kwramm
    Options
    Offline / Send Message
    Kwramm interpolator
    mLichy: cool project!
    I wrote a caching thumbnail based browser in PyQt once to run in Maya for browsing assets. Quite a good learning experience!

    How are you caching the thumbs? I used a sqlite database in my approach - one for each folder, which would get purged after X weeks, to keep the thumb cache size in check. I recently started porting this to C++...
  • mLichy
    Options
    Offline / Send Message
    animax - You may need to download Dotnet4.0 on your x64 machine for this to work. I thought windows would have installed it, but maybe not.

    For anyone crashing, try installing Dotnet 4.0 and let me know if that fixes it...


    Denny - I will look at the Drag/Drop right now quick. I think I might know whats wrong. Either way, I'll get it sorted. I think I may have forgot to add Drag/Drop support when you add new imageSets. But instead only add on load.

    I'm not sure why DoubleClick doesn't work.... I'll look at that too. But I've used it alot already and it has worked consistently for me it seems.

    Kwramm - Thanks! I came up with my own approach for caching, and didn't really look into any other methods, which maybe I should/could. I'm saving resized images to a cache folder, named a certain way for consistency, based on their original names. Then I do the same, and store all the entries in 1 xml. This may come back to bite me, but we will see.

    I also store image width/height/alpha boolean and path with the image as well.

    Then I have a seperate xml for imageSets, that just store a Path. I have 1 function that takes care of add new images/updating/finding cached images/ and creating/updating Audio/Video thumbs as well.

    Oh, and I also have an auto-Cache cleanup, but i should set mine to 2 weeks or something, like I was planning.
  • mLichy
    Options
    Offline / Send Message
    Updated the downloads on my site.

    I did in-fact forget to add doubleclick and drag/drop support on new imageSets. I thought I tested this... : \ Should work fine now :)

    http://www.matthewlichy.com/bitmapResourcer.html


    Oh, and also maybe instead of running x64 for those crashing, try x32, or just use that one. There shouldn't really be any difference as far as speed is concerned. Speed comes down to CPU/Ram availability and hard drive speed really.


    Edit: I just reuploaded them again quick. I added Z (zoom) support for the Alpha Icon now too.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    I got my Bitmap Font tool working in Unity

    7106160449_866c994887_o.jpg

    screen from shoeBox where the Bitmap font file is generated based on a Photoshop design

    6953483794_77b359a6b6_o.jpg
  • mLichy
  • Kwramm
    Options
    Offline / Send Message
    Kwramm interpolator
    mLichy wrote: Ā»

    Kwramm - Thanks! I came up with my own approach for caching, and didn't really look into any other methods, which maybe I should/could. I'm saving resized images to a cache folder, named a certain way for consistency, based on their original names. Then I do the same, and store all the entries in 1 xml. This may come back to bite me, but we will see.

    I also store image width/height/alpha boolean and path with the image as well.

    Then I have a seperate xml for imageSets, that just store a Path. I have 1 function that takes care of add new images/updating/finding cached images/ and creating/updating Audio/Video thumbs as well.

    Oh, and I also have an auto-Cache cleanup, but i should set mine to 2 weeks or something, like I was planning.

    Yeah I had something like this first, but then I ended up not feeling comfortable with all those small files on the HDD. Sqlite has the added benefit of doing all the sorting and filtering for me.
    Now in the C++ version it even supports threading. 4 independent threads speed up thumb generation quite a bit. Shame it doesn't work that way in Python.

    First I just scan the dir, update the DB - delete old entries, add new entries, but without the binary data. Then I start the threads and the thumb generation begins and the thumbs get inserted in the db.
  • mLichy
    Options
    Offline / Send Message
    hmmmm..... Yeah. I will have to look into that (sqlite). Right now something like 1000 images though is only 50MB of HDD space or something. So its not that bad. But if I could speed it up/use less space or whatever, that would be awesome.
  • Denny
    Options
    Offline / Send Message
    Denny polycounter lvl 14
    Everything is working well on my side now. :)
  • mLichy
  • Kwramm
    Options
    Offline / Send Message
    Kwramm interpolator
    sqlite is quite fast for me. I didn't choose it primarily for the speed though. I just hate to have a folder with 10.000s of small files (yes, I did scan my reference and texture archives at one point).
    Inside the sqlite I store the thumbs as either png (for alpha) or jpg to save some space. I store image size, format, if it has an alpha, date and size so I can sort/filter the db for that. I never load a whole folder's thumbs into memory either. I wrote a small cache class and then the thumbs are loaded live while you browse the pictures (via an itemdelegate in Qt) - it's amazingly fast, even in Python on my Core 2 duo macbook air. Almost no stutter and the memory footprint is quite low (except on Python where Qt itself adds 32mb right away).
    Except for the threading the C++ version is pretty much a port of the Python browser I wrote, but the main work is done by Qt for me. The Python version is written for my company but I might release the C version once I got the picture viewer part done...I kinda want a xnview like program, but simpler, because on OS X there's just no such viewer available (tried adobe bridge, Xee, the buggy xnview version and more...)
  • mLichy
    Options
    Offline / Send Message
    I was checking out the main site. Can this be used/ easily used in c#?

    I do like the idea of the thumbs at least being in 1 database file.
    Would the end user have to install it, or is it a dll reference ?
  • Kwramm
    Options
    Offline / Send Message
    Kwramm interpolator
    I'm not really a C# user. The end user doesn't need to install anything though and it comes as dll. I know some people have been using it with C# in Unity. That's where my knowledge regarding C# and sqlite ends. Otherwise it's just your standard SQL database, except its disk based and can handle concurrent access. It should be pretty light-weight too...Google maps on the iphone uses it for example.
  • mLichy
    Options
    Offline / Send Message
    Yeah, I read it can be used on phones. I will have to look into it more. It's very interesting. Not sure how worth it would be for me to do it or not. I'm not abandoning the idea though. I'll read into it more and go from there :). Thanks

    Edit: I found this, http://www.dreamincode.net/forums/topic/157830-using-sqlite-with-c%23/

    Seems to be pretty easy, and similar to using XML. How do you add files then? The same kind of way?

    Edit: Ok, I'll just have to keep googling, heh. Found this, which might be similar to how u do it.

    http://www.codeproject.com/Articles/196618/C-SQLite-Storing-Images
  • nyx702
    Options
    Offline / Send Message
    I updated my Zbrush Plugin with the Quick Load scripts I was tinkering with a few pages back. If you are interested feel free to check out the thread.

    http://www.polycount.com/forum/showthread.php?p=1572949#post1572949
    zbrush_plugin.jpg


  • Kwramm
    Options
    Offline / Send Message
    Kwramm interpolator
    yup, I just put the png/jpg thumb in the db as blob.
    first I scan the folder and insert new records in the db
    Then I start the thumbnail generation thread and it updated the records by adding the blob data.
    You can even start multiple threads which do thumb generation itself. Sqlite can handle this. The real bottleneck though is the file access because you're just writing into one single db file. The main speed increase is from generating the thumbs in parallel. I found that up to 3 - 4 concurrent threads you really notice a speed increase
  • mLichy
    Options
    Offline / Send Message
    Nice. Yeah, I started looking at it last night, and it seems pretty straight forward. I have FreeImage integrated into the method, so I can read in PSDS and Raw, then save those to the DB.

    Although, right now Im having to save them to a temp png, and load that into the DB. But I SHOULD be able to get the freeimage bitmaps bitarray, and just store that, right?

    I was having issues with it, but I don't see why it wouldn't work. Unless the DB needs to get the file header info and whatnot.

    Here's what the code looks like basically:
    //Retreave image from file and binary it to Object image
    using (FileStream stream = File.Open(FileLocation, FileMode.Open))
    {
    BinaryReader br = new BinaryReader(stream);
    byte[] data = br.ReadBytes(maxImageSize);
    image = new Image(dlg.SafeFileName, data, fileSize);
    }

    But, I should be able to remove the binary reader and set the data to the bitarray?
  • mLichy
    Options
    Offline / Send Message
    I figured out how to get a bitmap into a stream in FreeImage, and save/load that from the database. It's actually very fast now :) . All I had to do was,
    MemoryStream strm = new MemoryStream();
    FreeImage.SaveToStream(dib, strm, FREE_IMAGE_FORMAT.FIF_PNG);
    image = new Image(programDir, strm.ToArray(), 0);
    I need to work out some kinks with alpha in the PNG, but overwise, this might work really nicely.


    Edit: WOW! Caching them originally might be a little slower, need to test more. But, loading from the DB was instant! I click on the exe, and bam, is open right away showing like 16 images added to my flowlayoutpanel right away! Very impressive!
  • Kwramm
    Options
    Offline / Send Message
    Kwramm interpolator
    great to hear it works for you :) I'm a big fan of sqlite.
    What's also a neat feature of sqlite are in-memory databases. Instead of writing the data to a file, sqlite keeps it all in memory. We used this once in a tool for Maya which allows you to give tags and other additional properties to objects in Maya and then quickly do complex searches for objects.

    for inserting and updating the database: make sure you use transactions! so the data gets committed at the end of all updates / inserts and not after each individual update or insert. this can give you great speed boosts.
  • Mark Dygert
    Options
    Offline / Send Message
    A few weeks ago I was working on a "double tap" script for max. It is a way to reuse keybinds, press the key once one thing happens, press it again quickly within a narrow window of time and it triggers something else. But I hit a snag with tracking time, but the guys over at TechArtist.org and their knowledge of some undocumented maxscript "timestamp()" got it working great, so I release it into the wild! Be FREE!

    Here is one example that toggles the move gizmo between local and view if double tapped and if single tapped just activates the move gizmo leaving the reference coordinate system as it was previously set. As an animator I'm constantly cycling between local pivot to rotate and view pivot to move.

    The script: http://dl.dropbox.com/u/2336353/VigTools-ToggleMove.ms
    To install: Run the script once from anywhere. Use Customize > UI to assign it to a key.
    Use: Feel free to slice this up any way you need it to fit your needs.
    macroscript ToggleMove
    Category:" VigTools"
    toolTip:"ToggleMove (Q)"
    (--MOVE
        max move--switch to move mode first
        global lastClickedMove --defined but left blank for now
    
        fn RefCoordCycle_LV = (--Cycles the RefCoordsys between Local & View
        if getRefCoordSys() == #local then (
            toolmode.coordsys #view
        )
        else (
                toolmode.coordsys #local
            ) 
        )
        
        fn checklastClickedMove = (
            local thisClickedMove = timeStamp()
            if lastClickedMove != undefined then (
                if (thisClickedMove - lastClickedMove) < 500 do (--adjust this value to shorten or lengthen wait time
                    max move
                    RefCoordCycle_LV()--Switch this function with your own
                )
                lastClickedMove = thisClickedMove
            )
            else (--switch gizmo to move, ignore pivot setting, update "lastClickedMove"
                max move 
                lastClickedMove = timeStamp()
            )
            OK        
        )
    
        checklastClickedMove()
    )
    
    Other examples:
    Single tap - Quick Align. Double tap - Align Dialog
    Single tap - Move Gizmo. Double tap - Move Type In Dialog
    Single tap - Weld. Double tap - Target Weld
    Single tap - 3D Snap Toggle. Double tap - Angle Snap Toggle
    Single tap - cut. Double tap - slice
    Single tap - relax. Double tap - Relax Dialog

    So there you go, use it however you need to and if you have any questions post here and if I don't respond, hit me with a PM.
  • darthwilson
    Options
    Offline / Send Message
    @mark, you and your crazzy scripts! Sounds awesome though =D

    I've finished my Customisable character system for UDK!!

    [ame="http://www.youtube.com/watch?v=AzQAIKIgq2Y&quot;]Character Customisation Prototype in UE3 - YouTube[/ame]

    At a later date I'd like to team up with a programmer and scaleform artist to work on a UI..

    Then I might also work on making him playable in a game!
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    the Bitmap Font tool of ShoeBox plays now nice with tiny pixel fonts
    7115954021_bda23cb0fa_o.jpg

    Settings panel
    7115956969_26156b33ab_o.jpg
  • havardsc
  • mLichy
    Options
    Offline / Send Message
    Kwramm - Can you provide a transaction example/webpage if possible? I can keep looking, but I haven't found anything describing what you explained. You meant, collect all my changes, and then at the end , add them all as 1 lump sum into the database?
  • Kwramm
    Options
    Offline / Send Message
    Kwramm interpolator
    transactions go basically like this:
    try {
    * start transaction (command depends on the db engine)
    * update
    * update
    * insert
    *...until you're done
    * commit (<- stuff gets written at this point)
    }
    catch {
    rollback
    }

    Let's say the last insert fails and leaves your db in an incomplete state. Then you can issue a "rollback" command and everything up to the start transaction command will be undone. Those are the 3 transaction related commands almost all dbs offer: "start transaction", "commit (aka end transaction / write stuff to db)", "rollback (undo)"

    note: you don't have to do a rollback if an error occurs. rollback is just used if you update multiple tables and where your db could end up in an inconsistent state if one or more tables don't get updated. It's really about data consistency.

    Since transactions just require a few extra commands, there's no need to rewrite your entire db code. just insert the transaction commands into your existing code where they make sense. easy! :)

    Depending on what you're doing you may or may not see a speed increase. In my case it's quite big speed boost when I do a lot of inserts or updates (i.e. when I scan a folder). I'm not using transactions when I generate the blobs in the thumb generator thread though, because I need to write and commit the blob to the db as soon as it's ready so it immediately shows up in the db and the user can see the thumb as soon as the thread created it.
    If I would use a transaction here, then the user would have to wait until all thumbs for a folder are generated before he sees something. In total it might be faster, but most people prefer instant gratification, so I won't let them wait ;)

    I'm accessing sqlite via Qt, so any code I Have is probably not useful for you as Qt wraps everything in its own classes. But check out this page: http://www.sqlite.org/lang_transaction.html

    sorry for not being able to help more, but I think this should put you on the right track
  • mLichy
    Options
    Offline / Send Message
    Awesome, thanks dude! I will have to try that out this weekend.

    I managed to setup my test App to know if it needs to add/update a blob now, and does so properly. Next I want to do the Transaction thing, and look at adding the new items/updating, and then threading the creation/updating of the blobs as you said.

    I need to see if I can have multiple threads pushing updates to the WPF window though. Right now I can use 1 thread to update it, but not sure about 2-4.
  • mLichy
    Options
    Offline / Send Message
    Hm.... after looking around and reading this, http://stackoverflow.com/questions/3153458/wpf-how-to-load-lots-of-large-images-fast-into-wrappanel

    It seems like the approach I currently am doing, might be the best. I was hoping to Multi-Thread creating/adding the blobs to the DB, then adding to the View with realtime updates.

    Currently I can push the new element to view as they are created just fine. But they are all in the same loop/thread. It sounds like multiple threads might either not work or be slower.

    Like you said, I could thread adding to the Database probably, but then the user would have to wait for that to happen and then see them adding to view....... Which I could also do. I could maybe have a Progress Bar showing the % done when creating the blobs, then when thats done, show progress as they load into view like they do currently.
  • Fang
    Options
    Offline / Send Message
    Fang polycounter lvl 7
    beginning my foray into writing shaders. Inspired by Ryan James Smith fine work.

    sandshader.gif
  • mLichy
    Options
    Offline / Send Message
    Kwramm - So, I still need to do the Transaction stuff yet, and maybe some other optomizations. I'd like to thread creating thumbs, but still not sure if I will do that or not.

    But in any case, after testing between both methods I have, it seems like the DB method is faster overall. If I load the images from the DB directly and not from image paths, its crazy fast. Literally 10x faster. It can load like 240 images in 3 seconds from the DB, vs. 34 seconds loading checking against filepaths.... So I'd like to see if I can somehow get that same perf.

    But caching with my old method took like 1:32 minutes to cache 243~ images, and the DB method took 1:08. Loading back from the cache in both methods was the same, for right now.


    Edit: So I got a Parallel.ForEach loop in there now, processing the Database stuff first, then after that, adding the images to the view.

    Using 4 cores, processing big files especially, it was 2-3x faster than my other method. The only thing that sucks is, the UI is locked/non-updating while running the multi-core code. But then once its done, the UI updates per thumbnail like usual.

    Maybe I can create a new window, with a continous moving progressBar saying its building the cache, then close on finish and load them into view.

    After seeing that big of a improvement though, it's hard to not to want to use it.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    Bitmap fonts in combination with CSS prototype
    http://renderhjs.net/shoebox/cssBitmapFont/

    7121953743_dc4dc4e2e9.jpg
  • mLichy
1181921232456
Sign In or Register to comment.