PDA

View Full Version : Tutorial Scaleform UI without Flash: Vectorian Giotto and FlashDevelop



DonaldM
06-27-2011, 03:50 AM
This tutorial will examine using Vectorian Giotto and FlashDevelop as an alternative to using Adobe Flash. Adobe Flash is a great tool but not everyone can afford it! Even if you can you may wish to use this alternative tool chain as you may find you like the tools better. I like video tutorials for some things but I believe I would lack the ability to create a good one. If anyone wants to have a go at making a video tutorial based on these steps then they have my encouragement and permission.

We will be using a method where we create our content in Vectorian Giotto (creating a "dummy" swf) and then injecting our AS2 code into this swf file using FlashDevelop (which uses MTASC or Motion-Twin ActionScript 2 Compiler. This compiler is very stable and actually much faster then the compiler used by Flash itself! So this toolchain can actually have some advantages.).

Step 1: Install Vectorian Giotto.

The first step is to download and install Vectorian Giotto. This tool will be used to create our graphical content (actionscript will not be done through this program). You can download Vectorian Giotto from here: http://vectorian.com/giotto/

Step 2: Install FlashDevelop.

The second step is to download and install FlashDevelop. You can download FlashDevelop from here: http://www.flashdevelop.org/wikidocs/index.php?title=Main_Page.

Since the current release of Scaleform (at the time of this writing) does not support AS3, there is no need to download the Flex SDK but since AS3 support could be added to Scaleform rather soon it may be a good idea to go ahead and let the FlashDevelop installer download/configure that for you.

Step 3: Create GUI in Vectorian Giotto
The next step is to begin to create your desired UI in Vectorian Giotto. This is very similar to how you would create a GUI in Flash, but it can be a bit new so I will go into detail about the steps. Keep in mind this: SAVE OFTEN! This program is not the most stable in the world but it is free. If you hate losing work then you will want to hit save often so if the program DOES crash you can simply reload your file.

Step 3.1: Configure Document Properties
Now for the fun part! Open up Vectorian Giotto. You should see a screen that looks like this:

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_1.jpg

The first thing that you need to do is to edit the document properties. Go to Modify->Document. You will then see the Document Properties dialog. You can enter the desired dimensions, frames per second, and background color using this dialog. I will choose to use a width of 1280, a height of 720, and an fps of 30 as that is similar to the settings of the UDK front end. You can use alternative dimensions if you would like.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_2.jpg

Step 3.2: Create background layer

Now in this current layer we will want to create a simple backdrop. Leaving the stage visible will be interpreted by UDK as transparent areas. If you are making a HUD then you would want your stage to be visible in any area that you want to see the game content.

We can simply use the Rectangle tool in the toolbar and change the brush color to whatever color we want. I think for this tutorial I am going to make my background a nice dark blue color. NOTE: You can change the zoom level using the scroll wheel.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_3.jpg

Fantastic! We now have a background. We can edit the layer name towards the top left of the screen and I would suggest calling this layer "Background". We at this point probably also want to lock this layer to prevent accidental modification. You can simply Double click the layer name to edit the name of the layer. Then to lock the layer click the lock icon.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_4.jpg

Step 3.3: Save progress in UDKGame\Flash\somenamehere directory

Now is a great time to save! Let's save this project somewhere so we don't lose all of our work. I recommend saving to your own folder inside of the UDKGame\Flash directory. For this tutorial I am going to call it VectorMenuTut so my path will be UDKGame\Flash\VectorMenuTut . I am going to name my project VectorMainMenu.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_5.jpg.

Now we will want to hit save very often so that if Vectorian Giotto crashes we do not lose a good deal of work!

Sidebar: About CLIK Components

We are now going to start creating a button. Now some at this point might be wondering about the CLIK components. Now the problem is that while a lot of the code that makes these widgets work is in .AS files which we could use no problem with FlashDevelop, the FLA files we cannot use. If some industrious person (and probably not me) were to make ports of the components that work with this tool chain (Basically this would involve creating usable swf files from the fla files, seperating the AS code from the components (so we have dummy swf files), and then configuring a FlashDevelop project that injected these swf files with the action script code... It is possible but probably a good deal of work... I might do it if I get really bored one day...).

DonaldM
06-27-2011, 03:50 AM
Step 3.5: Adding the button layer

You now want to add a new layer for the menu buttons.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_6.jpg

Where I have my mouse pointer is where the button is to insert a new layer. I went ahead and renamed it to "Buttons" and it should be ABOVE the Background layer (or you will not see the buttons!).

Step 3.4: Creating the button base

Right so the next step is to draw the base that will be used for our button (Make sure the Buttons layer is selected). I will use the Rounded Rectangle tool and simply draw a button the size that I want one of my buttons to be (you can resize it later if you mess up). You can access the Rounded Rectangle tool by clicking the drop down arrow on the Rectangle tool. You also want to change the brush color to the base color that you want your button to be. I am trying to keep this simple so I will leave all of the fancy effects to the artists!

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_7.jpg

Step 3.5: Convert button base to Button symbol

Switch to the selection tool (The mouse pointer looking thing) select all of the button base you just made and right click. From the context menu select Convert to symbol or just hit F8. This will bring up the Insert into library dialog. You will want to select Button for the type and for the name I am going to call this playBtnSymbol although you can call it what you like. Just remember that eventually you will need to give the button on your menu a name (which will be used in the ActionScript) and so you probably don't want to name it what you want to call the instance of this button.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_8.jpg

Also you should see a Properties editor towards the bottom of the screen. Here you will enter a name that this particular instance of the button will have. I will name it playBtn.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_9.jpg

Step 3.6: Editing the button symbol and adding text

Now we can double click on this button component to edit it.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_10.jpg

A blank button is not very fun, so we will want to use the text tool to label the button. I will specify a font size of 30, pick a font, and set my brush color to white. Then I will write "Play Game" and center the text as best I can inside of the center of my button base.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_11.jpg

Step 3.7: The Over frame

The nice thing about using the Button symbol is that we can have rollover and click frames. I am just going to make an effect when the mouse is over the button. Right click the cell directly under Over and select Insert Keyframe from the context menu.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_12.jpg

Now we can edit this frame by filling in the button base with a highlighted color (you can do any effect you like here, but once again I am trying to keep things simple!)

KEEP SAVING YOUR WORK!!!!!

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_13.jpg

We are done editing this button so we can click Go to movie at the top of the screen.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_14.jpg

DonaldM
06-27-2011, 03:51 AM
Step 3.8: Duplicate button and edit text

Make sure the Library is visible by going to Window->Library. In the library window, right click the playBtnSymbol object and select Duplicate from the context menu.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_15.jpg

We can now rename this symbol to exitBtnSymbol. Just right click it in the library (it should be blank) and select rename from the context menu. Also drag the exitBtnSymbol onto the stage, right below the play button.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_16.jpg

Unfortunately both buttons say Play Game so we will need to fix that! Double click the symbol we just added to bring up the button editor. Use the text tool to edit the text on both the Up and Over frames.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_17.jpg

Once you are finished you can click the Go to movie button towards the top of the window.

Also your going to want to name the instance of this button something. I set it to exitBtn and advise you to do the same so that the actionscript works!

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_18.jpg

Step 3.9: Create mouse cursor

We want our menu to have a cool custom mouse cursor. For this tutorial I am just going to draw something simple, convert it to a movie clip, and then name the movie clip instance so that my actionscript can find it.

Create a new layer and name it cursor.

Set your brush color (I chose white) and use the brush tool to draw a sort of angled mouse cursor thing.

Select what you just drew, right click and say Convert to symbol. I will name it cursorSymbol and select Movie Clip as the type.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_19.jpg

In the properties I am going to name the cursor instance cursor.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_20.jpg

That's it! We have created the design for our menu! Now we can proceed to the last step!

Step 3.10: Save final project, export to SWF

Save your work and then go to File->Export flash movie. When I save this for reasons that will become apparent, I am going to tack on the to the name of VectorMainMenu _Dummy so that the file name is VectorMainMenu_Dummy.swf

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_21.jpg

Once you hit save then you will see a dialog asking about compression. I have not played with this option and I do not use compression. This is a simple file so I don't think compression will help much but feel free to try it. The fact of the matter is that we are going to be compiling a new SWF file using FlashDevelop so I do not think it will matter. My advice (since I do not know) is to just avoid using compression for the dummy file.

Ok so what we have just done is create our dummy swf file. It does not contain any actionscript code and so when we run the swf it will not do anything very interesting. We can test the swf file to see how it looks anyway. Go to the folder and double click the swf to launch the flash player (You could probably also open it in the Scaleform player but I have not gotten to that yet.)

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_22.jpg

When you move your mouse over one of the buttons, the button should turn green. This allows the player to see that it is infact a button (which is helpful!). Sorry if I state the obvious, but I am trying to aim this tutorial at all skill levels.

DonaldM
06-27-2011, 03:53 AM
Step 4: FlashDevelop

We are finally at Step 4! If you have made it this far then you have a dummy swf containing the menu. We need to add some code to make this actually work the way that we want it to. (At this point in writing the tutorial it is 2 A.M. so I will stop here for the night!)

To do that we are going to setup our FlashDevelop project, add a src folder, add an .as file containing the code we want, and then setup our project to use injection to inject the code into the swf file and output the swf file with our code! We want to keep track of which file is the dummy and which is the final swf file with code so that is why I had you append "_Dummy" to the end of your swf file. In my opinion it just makes the work flow a bit cleaner!

Step 4.1: Launch FlashDevelop

When you first launch FlashDevelop you should see something similar to this:

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_23.jpg

Step 4.2: Create new project
We want to create a new project so go to Project->New Project. In the New Project dialog scroll down to the ActionScript 2 project types and select Empty project. For the name enter VectorMainMenu. For the location navigate to where your VectorMenuTut folder is that you created in the UDKGame\Flash directory. My path is C:\UDK\UDK-2011-05\UDKGame\Flash\VectorMenuTut Your path will be different depending on your drive, UDK name, build date of UDK, ect. I am not going to chose to create a new directory for this solution but you can if you want to.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_24.jpg

Step 4.3: Add src folder and class, set class to always compile
On the right side of the screen you should see the Project Manager. Right click the VectorMainMenu (AS2) project and from the context menu select Add->New Folder. Name the folder src and press enter to accept the name. Now right click the src folder and select Add->New Class. I will name the class the same as the swf file so enter VectorMainMenu into the Name field of the New Actionscript Class dialog.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_25.jpg

In the Project Manager right click the VectorMainMenu.as file and select Always compile from the context menu.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_26.jpg

DonaldM
06-27-2011, 03:53 AM
Step 4.4: Editing VectorMainMenu.as

Now we can edit the VectorMainMenu.as file which will contain the ActionScript to make our menu work!

The current code should look like this:



/**
* ...
* @author Donald May
*/
class src.VectorMainMenu
{

public function VectorMainMenu()
{

}

}


You can choose to keep the package src. or you can rename the class VectorMainMenu like so:



/**
* ...
* @author Donald May
*/
class VectorMainMenu
{

public function VectorMainMenu()
{

}

}


Alright so we will need to add a static main function to this class to serve as our entry point.



/**
* ...
* @author Donald May
*/
class VectorMainMenu
{
//serves as the entry point!
static function main(mc:MovieClip):Void
{

}
public function VectorMainMenu()
{

}

}


We will need to add a variable to hold an instance of our VectorMainMenu class and call the constructor function in our entry function main:



/**
* ...
* @author Donald May
*/
class VectorMainMenu
{
static var vectorApp:VectorMainMenu;
//serves as the entry point!
static function main(mc:MovieClip):Void
{
vectorApp = new VectorMainMenu();
}
public function VectorMainMenu()
{

}

}


Now our constructor VectorMainMenu will be called!

MAKE SURE TO SAVE YOUR WORK!

Let's do this in stages. The first thing we will do is to hide the mouse cursor. We can add that line to our constructor!



/**
* ...
* @author Donald May
*/
class VectorMainMenu
{
static var vectorApp:VectorMainMenu;
//serves as the entry point!
static function main(mc:MovieClip):Void
{
vectorApp = new VectorMainMenu();
}
public function VectorMainMenu()
{
Mouse.hide();
}

}


Now to test to see if we have things working correctly, we can combine the dummy swf and as file and produce an output swf file with code.

DonaldM
06-27-2011, 03:54 AM
Step 4.5: Setting up the project properties

Go to Project->Properties. This will open up the VectorMainMenu (AS2) Properties dialog. Specify for the output file VectorMainMenu.swf then specify the width and the height to be the same as the dummy swf we created (1280x720).

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_27.jpg

Now go to the Classpaths tab. Click the Add classpath button. Navigate to the src directory you created (inside of the VectorMenuTut folder) and select ok.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_28.jpg

Finally go to the Injection tab. This is where the magic happens! Check the Enable code injection checkbox and then navigate to the dummy swf file we created.

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_29.jpg

When you are done with all of that click Apply and then click Ok.

Now go to Project->Build Project or hit F8

If all goes as planned you should now see VectorMainMenu.swf in the VectorMenuTut folder! Run this swf file and you should see the following:

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_30.jpg

The mouse cursor has vanished! We were successfully able to inject our actionscript code into our dummy swf file! However notice that the nice cursor we made is not following the mouse. We will need to edit the VectorMainMenu.as file to make this work.



/**
* ...
* @author Donald May
*/
class VectorMainMenu
{
static var vectorApp:VectorMainMenu;
//serves as the entry point!
static function main(mc:MovieClip):Void
{
vectorApp = new VectorMainMenu();
}
public function VectorMainMenu()
{
Mouse.hide();

var mouseListener:Object = new Object();

mouseListener.onMouseMove = function ()
{
// Set the cursor instance position to the mouse position.
_root.cursor._x = _root._xmouse;
_root.cursor._y = _root._ymouse;

updateAfterEvent();
};

Mouse.addListener(mouseListener);
}



So we add a variable to hold our mouse listener, define a function that will occur when the onMouseMove event is triggered, and set the x,y positions of our cursor movieclip to the x,y positions of the mouse. We use _root to access movieclips and properties that we put at the stage level. We call the updateAfterEvent function to refresh everything after changing the cursor's position. We also need to add this mouse listener.

If we build our project (hit F8) and rerun our output swf we should see the following:

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_31.jpg

Our mouse cursor now follows the mouse! Fantastic!

That does it for this tutorial! We have produced an swf file and added actionscript 2 code to it using the code injection technique. We can now use this swf file using Scaleform just like we would use one created in Adobe Flash. Rather than rehash the same subject I recommend you do research and find a nice tutorial to do that! You should have all the basic understanding you need to create Scaleform UI's without Adobe Flash.

You can download a complete zip containing all of the things shown here from my website (http://www.donaldsmay.com/VectorMenuTut.zip)!

I thank you all very much for reading what has become a very very long tutorial. This tutorial has taken me some amount of time so if you like it, please feel free to say so! It will help motivate me to want to make more tutorials in the future :) .

DonaldM
06-27-2011, 03:59 AM
Oh and yes it does work:

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_32.jpg

http://i16.photobucket.com/albums/b48/shadowisadog/Vectorian%20Giotto%20Scaleform/giotto_33.jpg

I guess when you have 30 images in one thread, what is a couple more lol!

And there you have it :) . It seems to work just fine, it is only a little bit more complex then using Adobe Flash (once you know what to do ;) ) and it provides a nice tool chain with the best of both worlds! It has nice designer features (drag and drop, ect) with code completion through FlashDevelop. Best of all the tools are Completely Free! You can't beat that :) .

kiriri
06-27-2011, 09:45 AM
wow that was amazing, I like it a lot! It's quite amazing how you can create an interactive UI without spending one penny :D

Thanks!

Matt Doyle
06-27-2011, 11:24 AM
Fantastic job! And another free Flash editor I did not know about. I'll link to this thread in the Getting Started post.

DonaldM
06-27-2011, 09:46 PM
Thank you :) . Yeah it took me a good while to find Vectorian Giotto but I had a good idea of what I was searching for in a tool. A lot of the other free options required doing things almost entirely through code so I hoped in this tutorial to present a more graphical alternative.

Just a note to people reading, I tested fscommand and the ExternalInterface as well. I can vouch that fscommand definitely works and ExternalInterface compiles, although I have not tested it yet. I think this method should work fine though for all uses.

The only thing I have not done yet is to embed image resources (bitmaps) in this workflow and have then used in UDK. I am sure it is possible but I have not done it with this workflow yet. If I were to do a new tutorial I would do something much more code heavy like an inventory or config screen.

MaVmAn
07-02-2011, 08:03 AM
Thanks for the tutorial, seems to be a good alternative to flash. I definitively will try it even if I see coming complications for replacing CLIK assets and using US.

clintonman
07-02-2011, 10:33 AM
Nice job and Vectorian looks like great find.

N3M3SIS
07-05-2011, 08:16 PM
Nice JOB ! .... Now ... doing... tutorial...

Thank you

Saishy
07-05-2011, 09:44 PM
The only thing I have not done yet is to embed image resources (bitmaps) in this workflow and have then used in UDK. I am sure it is possible but I have not done it with this workflow yet. If I were to do a new tutorial I would do something much more code heavy like an inventory or config screen.
I tested FlashDevelop some time ago and found it quite hard to embed bitmaps into the file.

I stopped using it before I had any success, but let me just say that the community is not that organized.

DonaldM
07-05-2011, 11:36 PM
The good thing is that you would embed the bitmaps through Vectorian Giotto and not FlashDevelop. The code injection technique actually disables the ability to embed content anyway.

Thank you for the feedback though! Your game looks great btw.

NekoDemon117
07-06-2011, 08:08 PM
This Tutorial isn't working for me.

I keep getting this retarded error when attempting to build in FlashDevelop 4. I copy-pasted your code and tried to build with it instead. Same thing.


Running process: C:\Program Files (x86)\FlashDevelop\Tools\fdbuild\fdbuild.exe "C:\UDK\UDK-2011-06\UDKGame\Flash\VectorMenuTut\VectorMainMenu\Vect orMainMenu.as2proj" -ipc ee630f1f-d955-42f2-b706-7369681ae720 -version "1.14" -compiler "C:\Program Files (x86)\FlashDevelop\Tools\mtasc" -notrace -library "C:\Program Files (x86)\FlashDevelop\Library"
Building VectorMainMenu
Exception: startIndex cannot be larger than length of string.
Parameter name: startIndex
Done(1)

DonaldM
07-07-2011, 04:44 PM
Try adding a } at the end of the source, I might have left one off. Otherwise make sure you have added the src folder to the classpaths.

NekoDemon117
07-07-2011, 08:39 PM
Try adding a } at the end of the source, I might have left one off. Otherwise make sure you have added the src folder to the classpaths.

After much frustration, I actually figured out what caused the exception. Somehow I had both the src folder and the class file set to always compile. I had to turn off the "always compile" on the folder, so that only the class had that property. Of course I didn't find this problem out until after I had already uninstalled version 4.0.0 and installed 3.3.4 RTM to see if that was the problem.

Then the "cursor follows the mouse" code didn't work. The code correctly compiled; it just didn't do any good. I found out that was because the code was only compatible with Vectorian Giotto's free-draw tool objects, and not anything drawn using the rectangle or oval tools. So I had to go back and delete the cursor object and free-draw a new one on the Cursor layer. After that, the code magically worked.

I got it into UDK and loaded into my level in play-in-editor using Kismet, though I'm not sure how to make the buttons actually do more than just highlight/un-highlight. Do you have a picture of the rest of your Kismet page?

P.S. Thank you for making this tutorial. I learned a lot once I finally got it figured out.

DonaldM
07-08-2011, 03:23 AM
Hello NekoDemon117,

That is very odd. If you draw inside of the cursor movieclip it should work with any tool. I will try to test this later and see what the problem is.

Making the buttons do something involves doing something similar to this:

Put:



import flash.external.ExternalInterface;


At the top of the file and:



_root.exitBtn.onPress = function ()
{
ExternalInterface.call("ExitClicked");

}


after your cursor stuff in the actionscript.

And your welcome!

DonaldM
07-08-2011, 06:25 PM
So rather unfortunately Vectorian Giotto does not support saving imported images as png (loseless) rather than jpeg as of yet. Scaleform requires all embedded images to be png files. I have sent an email to the creator of Vectorian Giotto and asked if they can include support for saving the image resources as png files.

I am not giving up on this potentially working though and I am currently working on a small software utility which may allow a temporary fix to the problem.

I have been playing around with two .net SWF libraries to attempt to create a command line utility for turning the jpeg tags into lossless tags. I have had success getting information about the images from the swf file using SwfNet, but I like SwfDotNet's structure a lot better. While SwfNet supports up to SWF 8, SwfDotNet only supports up to version 7. I got some odd errors when attempting to use SwfDotNet to read the images... it said the header information was corrupted, but that is obviously a failing of the library as I was able to read the files using a variety of other methods. Luckily both libraries are open source... The idea behind the approach would be to go through and convert any jpeg tags in the swf file to loseless tags that can be read by scaleform. It shouldn't be extremely complicated, the trouble is just finding a library that can work as expected.

I am not without results so far for my efforts:

http://i16.photobucket.com/albums/b48/shadowisadog/MakeLoseless.jpg

DonaldM
07-09-2011, 03:46 AM
So I have been working the issue all day and I believe that I will have a tool ready by the end of the day tomorrow that will be able to make the toolchain work for images. It is a command line so you simply will drag your dummy object (or even your final object) and it will automatically find and convert all of the jpeg tags to lossless tags and save your swf with an appended _lossless to the filename. It took a lot of time because I had to do some modifications to the existing swf library for dotnet... and combined some code together. As I believe in sharing those changes I modified the DefineBitsJpeg2Tag.cs file of the SwfDotNet library as follows:



private void DecompileToStream(Stream stream)
{
BinaryWriter writer = new BinaryWriter(stream);

byte[] data = new byte[JpegData.Length];

Array.Copy(JpegData, data, JpegData.Length);

// first header
if (data[0] == 0xFF && data[1] == 0xD9 &&data[2] == 0xFF && data[3] == 0xD8)
{
byte[] copy = new byte[data.Length - 4];
Array.Copy(data, 4, copy, 0, data.Length - 4);
data = copy;
}
// cleans out bug markers in swf jpgs
int index = 2;
int len = data.Length;
while (index + 3 < len)
{
byte b0 = data[index];
if (b0 != 0xFF)
{
break;
}
if (data[index + 1] == 0xD9 && data[index + 2] == 0xFF && data[index + 3] == 0xD8)
{
// bingo
byte[] copy = new byte[data.Length - 4];
Array.Copy(data, 0, copy, 0, index);
Array.Copy(data, index + 4, copy, index, data.Length - index - 4);
data = copy;
break;
}
else
{
int tagLen = (data[index + 2] << 8) + data[index + 3] + 2;
index += tagLen;
}
}
writer.Write(data);
writer.Flush();
}


which is code I took from the Clean method of the DefineBitsTag.cs file of the SwfNet library (I determined that this method was what was causing my images to not decode correctly, not sure if it is a bug with the original library or the fact I am using a higher version of swf then the library was designed for)... and then... I modified the SwfHeader.cs MAX_VERSION constant in the SwfDotNet library to support a higher version (I used 8). It is in the latest build set to 7 which doesn't work for our purposes ._. .

Anyway that is what I have done so far with the following code:



static void Main(string[] args)
{
string filename = "C:\\UDK\\UDK-2011-05\\UDKGame\\Flash\\VectorMenuTut\\VectorMainMenu_ Dummy.swf";
if (filename != "")
{
string name = Path.GetFileNameWithoutExtension(filename);


string outputFilename = "";
if (args.Length < 2)
{

outputFilename = Path.Combine(Path.GetDirectoryName(filename) , Path.GetFileNameWithoutExtension(filename) + "_Loseless"+Path.GetExtension(filename));

}
else
{
outputFilename = args[1];
}

Console.WriteLine("File: " + Path.GetFileNameWithoutExtension(filename));
Console.WriteLine("Output to: "+outputFilename);

SwfWriter swfWriter = new SwfWriter(outputFilename);

SwfReader swfReader = new SwfReader(filename);
Swf swf = swfReader.ReadSwf();

SwfHeader swfHeader = swf.Header;
Swf modifiedSwf = new Swf(swfHeader);
Console.WriteLine("Width: " + swfHeader.Width);
Console.WriteLine("Height: " + swfHeader.Height);
Console.WriteLine("FPS: " + swfHeader.Fps);

IEnumerator curTag = swf.Tags.GetEnumerator();

int a = 0;
while (curTag.MoveNext())
{
if (curTag.Current is DefineBitsJpeg3Tag)
{
Console.WriteLine("Found JPEG with alpha!");

DefineBitsJpeg3Tag jpegTag = curTag.Current as DefineBitsJpeg3Tag;


Image curImage = jpegTag.DecompileToImage();


Console.WriteLine("Image width: " + curImage.Width);
Console.WriteLine("Image height: " + curImage.Height);

a++;


}
else if (curTag.Current is DefineBitsJpeg2Tag)
{
DefineBitsJpeg2Tag jpegTag = curTag.Current as DefineBitsJpeg2Tag;
MemoryStream pngImageStream = new MemoryStream();
Image curImage = jpegTag.DecompileToImage();
curImage.Save(pngImageStream, ImageFormat.Bmp);

Image pngImage = Image.FromStream(pngImageStream);

pngImageStream.Close();


Console.WriteLine("Found JPEG!");
Console.WriteLine("Image width: " + curImage.Width);
Console.WriteLine("Image height: " + curImage.Height);


DefineBitsLossLessTag losslessTag = DefineBitsLossLessTag.FromImage(jpegTag.CharacterI d,pngImage);
modifiedSwf.Tags.Add(losslessTag);
}
else
{
modifiedSwf.Tags.Add(curTag.Current as BaseTag);
}
}

swfWriter.Write(modifiedSwf);

swfWriter.Close();

swfReader.Close();



}
else
{
Console.WriteLine("Please supply a SWF on the command line! ");
}

Console.WriteLine();
Console.WriteLine();
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}



Still has a ways to go, but it is progress :). The logic is the follows:

1. Open an SWF file that we want to convert and iterate all of the tags.
2. If we find a JPEG tag then we want to convert that to a lossless tag. (I still need to test and add alpha transparency stuff also).
3. Otherwise for all other tags we simply want to readd them to the output swf.
4. Save the newly converted SWF.
5. Profit!

And yes... I know none of this is obvious, it is a good bit of work, and I am more than likely insane... but! It is an interesting challenge :) .

Matt Doyle
07-11-2011, 12:11 PM
This is great stuff you are doing for the community Donald. Your name shall be remembered!!

DonaldM
07-12-2011, 12:45 AM
Thank you Matt :) .

So I have actually achieved a working build of my software tool! The only downside is I had to do a drastic change to the SWF library I was using to force it to work correctly. Essentially I discovered a serious bug in the SwfDotNet library I was using that was creating corrupted SWF files for the GfxExporter tool. I solved it by only focusing on the Jpeg2 tag and simply re-exporting the rest, however I would like to get the library to work correctly. One big issue is that the library I am using was never meant to work with version 8 of the SWF file format, and I have spent days updating the library.

In the mean time I am prepared to launch the alpha version of my conversion tool by tomorrow. I apologize for the delay but there were a lot of technical issues I had to solve. For instance I now know that the image data of a lossless tag needs to be premultiplied by the alpha channel value! It is not an easy task (for instance the alpha channel data was zlib compressed so I had to decompress it to be able to use it. Figuring out the right way and then adding the alpha channel to the converted image was a pain!).

The tool does work and I just need to pop it up on my website and do a brief writeup as to how to use it. I will update the tool once I fix the bug in the library I am using, but that way it is up as quick as possible for anyone wanting to use it.

DonaldM
07-12-2011, 01:43 AM
I am proud to announce an early release of SWFMakeLossless!

Here is the link: http://twisted-pantheon.com/SWFMakeLossless.zip

It is a very simple command line utility. You can simply drag the SWF you want to convert on to the exe and it will produce an SWF with an added _Lossless in the same folder. Optionally you could specify in FlashDevelop to use the tool as a prebuild command and then inject your code into the lossless swf file (What I do).

So here is the new toolchain:

Make your content in Vectorian Giotto and save it with the _Dummy name convention. Run your tool through SWFMakeLossless (my tool) and end up with _Dummy_Lossless. Then inject your code using FlashDevelop on the _Dummy_Lossless file.

Download the Example project! (http://twisted-pantheon.com/VectorMenuTut_WithCursorImage.zip)

Here is a screenshot of it working in UDK:

http://i16.photobucket.com/albums/b48/shadowisadog/vectoriancursor.jpg

and my Vectorian image settings:

http://i16.photobucket.com/albums/b48/shadowisadog/vectoriancursor_vectorian.jpg

:) .

Note: There may be bugs. Keep in mind that I developed this tool from scratch myself. If you find bugs or it doesn't work then please let me know so I can fix it! Also once it gets more stable I can give a release build (this is a debug build for testing purposes). Also eventually I will share the source code. The only reason I don't is that the tool makes use of a library that I have edited substantially and I want to do more testing and developing before I share both. If you must have the source code now then please contact me via PM and I can try to arrange it.

Here is part of the conversion code though (so you can see part of what it does behind the scenes):


RGBA[] colorInfo = new RGBA[pngBitmap.Width * pngBitmap.Height];

BitmapData buffer = pngBitmap.LockBits(new Rectangle(0, 0, pngBitmap.Width, pngBitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

int pixelSize = 3;

for (int y = 0; y < pngBitmap.Height; y++)
{

for (int x = 0; x < pngBitmap.Width; x++)
{
byte a = alphaData[y * pngBitmap.Width + x];

byte b = (byte)(Marshal.ReadByte(buffer.Scan0, (buffer.Stride * y) + (pixelSize * x)));
byte g = (byte)(Marshal.ReadByte(buffer.Scan0, (buffer.Stride * y) + (pixelSize * x) + 1));
byte r = (byte)(Marshal.ReadByte(buffer.Scan0, (buffer.Stride * y) + (pixelSize * x) + 2));


double fa = a / 255.0;
b = (byte)(((b / 255.0) * fa) * 255.0);
g = (byte)(((g / 255.0) * fa) * 255.0);
r = (byte)(((r / 255.0) * fa) * 255.0);

Marshal.WriteByte(buffer.Scan0, (buffer.Stride * y) + (pixelSize * x), b);
Marshal.WriteByte(buffer.Scan0, (buffer.Stride * y) + (pixelSize * x) + 1, g);
Marshal.WriteByte(buffer.Scan0, (buffer.Stride * y) + (pixelSize * x) + 2, r);

colorInfo[x + y * pngBitmap.Width] = new RGBA(r, g, b, a);


}
}

pngBitmap.UnlockBits(buffer);


BTW: It uses the .NET 3.5 framework. If you don't have it then you need to download it: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=21 I think you can get it from there.

Also stay tuned! I am looking at adding some very unique features to this tool. The first is that if we already have a folder of lossless assets in the same folder as the SWF, why should we need to convert pixels of a jpeg image and risk artifacts? Instead an update to my tool is going to allow you to specify an optional folder of the lossless assets and if it finds one with the same name as the asset it is trying to convert, then it will use that one instead! Also I am going to research the potential to add pixel shader processing during the image conversion step (after we get the image from the jpeg or the file) so if say you want to convert all of the images to greyscale you will be able to supply a pixel shader on the command line arguments to do that (maybe if I can figure out a way to make it work).

EDIT: Pixel shader support does look possible but it would probably require the end user to get the DirectX SDK in order to have the shader compilation tool (which I would have to invoke as a process probably). Either that... or force the use of compiled shaders, but they would need to be written a certain way to work with my program. If there is interest perhaps I will be able to add this feature but I would like to hear from people if such a feature is even desirable. I think it would be cool, but not if it potentially alienates people who need to use the tool. It would also require the use of WPF (Windows Presentation Foundation).

Matt Doyle
07-12-2011, 11:44 AM
Nice! I've added a link to this forum post (the one about your tool) in the User Created Tools section at the bottom of the Getting Started sticky forum post.

FTC
08-11-2011, 05:21 AM
Hi,

First of all THANK YOU for opening this awesome possibility for us with this tutorial :)

But is there another way to use the menu, instead of fscommands?
I took a look at this tutorial http://www.youtube.com/watch?v=_iP4tRf3060 but I think the clik widgets are specially for the scaleform gui and I cannot access a simple textfield from Vectorian Giotto with them.

Now I do have to say I have absolutly no knowledge of Flash or Actionscript, and up to this point I never considered it because of the high price. Now I would like to know if (and how) I can use it with unrealscript before really investing time to learn it.

greetings

Matt Doyle
08-11-2011, 12:24 PM
Everything you need to know about using Flash/AS with UnrealScript can be found here:

http://forums.epicgames.com/showthread.php?t=743567

Also, check out the sample UI UnrealScript files in the dev folder.

FTC
08-11-2011, 04:27 PM
Thanks, I fixed it. It is still complaining about not finding the font, but I think I can figure that out myself.

However, it seems the WidgetInitialized event is not being called. I put a `Log("Test") in there but there is no output in the console. So I cannot use the buttons :/



class MainMenu extends GFxMoviePlayer;

var GFxClikWidget StartButton;
var GFxObject MainMenuTitle;

function bool Start(optional bool StartPaused = false)
{
super.Start();
Advance(0);

MainMenuTitle = GetVariableObject("_root.MainTitle");
MainMenuTitle.SetText("very long test text");

return true;
}

event bool WidgetInitialized(name WidgetName, name WidgetPAth, GFxObject Widget)
{
`Log("Test");
switch(WidgetName)
{
case('playBtn'):
StartButton = GFxClikWidget(Widget);
StartButton.AddEventListener('CLIK_press', OnStartButtonPress);
break;
default:
break;
}
return true;
}

function OnStartButtonPress(GFxClikWidget.EventData ev)
{
ConsoleCommand("open DM-Deck");
}

defaultproperties
{
WidgetBindings.Add((WidgetName="playBtn",WidgetClass=class'GFxClikWidget'))
}


greetings

FTC
08-12-2011, 07:13 AM
I fixed the font issue: In Vectorian Giotto you have to select your textfield an click the "Embed..." button in the properties panel. Then simply select the characters you need.

The play game button is still not working.

Also I tried implementing images and converted the swf with DonaldM's tool but it gives me a corrupted swf (That is what flash devlop says when it fails to compile). I cannot play the converted flash, it stays black. I use Win 7 64bit, might that be a problem?

greetings

FTC
08-13-2011, 11:37 AM
Ok, after a long search how to use regular flash buttons with udk I found this thread: http://forums.epicgames.com/showthread.php?t=756460
After doing that I remembered reading about ExternalInterfaces in the Getting Started links, but they never explicitly stated it for buttons (I admit I haven't read all of them thoroughly). One of the topics used delegates but apparently those would not work with FlashDevelop.
Nevertheless I now use ExternalInterface to call UnrealScript functions and it works :)

As for the SWFMakeLossless: I don't know why, but using the provided menu sample from the tutorial it works, no matter what image I insert into the document. However, using my menu, which I created following the tutorial, it does not work with any image, not even with the sample mouse cursur image.
I already redid the tutorial but it did not work either. I also tried to find differences between my menu and the tutorial files, but was unsuccessful. I will continue to search for the error and in case I can't find it I will just use the tutorial files and build my menu on top ;)

greetings

HavocInferno
08-23-2011, 02:15 AM
I got a question, as I am attempting to create a HUD using Giotto, I wanted to know how you can Convert an Object to a symbol->graphic. In flash it was Right Click -> Convert to Symbol -> Then choose graphic. In Giotto, I can only choose Movie Clip or Button...

Or could you maybe do a tutorial on how to make a HUD using Giotto? I know that's a big request, but I'm trying to use the SMU Guildhall Tut with Giotto and it's a mess because there's things in Flash which aren't there in Giotto.

daimaku
09-14-2011, 01:36 AM
thanks for the info !!!! really good !!!

TheWarlord25
11-03-2011, 03:57 AM
Does this even work for anybody? If I could get a mouse cursor to appear in UDK, just that, I would be amazed.

Update Edit: I got Sothink SWF Quicker and that puppy works! Very happy!

MrSide
01-19-2012, 02:08 AM
Hi!

I have found this thread very useful but I was wondering, would anyone know how to output a fs command when you press one of the buttons in FlashDevelop? Or just how to use a button press as an input for Kismet in unreal?

digitalseraphim
01-28-2012, 04:04 PM
@MrSide:
I was able to get fscommand working easily with Flashdevelop. Make sure you move the CLIK directory above your src directory in FD. You can set the "Project->Properties... -> Output (tab) -> Test Project " to "Run Custom Command" then click the "Edit..." button and put the following as your Command: "<path to your UDK-<date> dir>\Binaries\GFx\FxMediaPlayer.exe <path to your output swf>". This allows you to run the scaleform viewer right from FD, which makes things easier.

Alexbeav
02-01-2012, 07:53 PM
Excellent thread and tutorial, thank you very much for this. For a first-time game developer with no budget, tutorials like these are life savers !

Vaquero
02-17-2012, 06:14 AM
Is there a way to share resources between flash files in Giotto like there is in Adobe's Flash? So I don't have to embed every image for every swf and thus eat up my memory ingame? I just briefly looked at Vectorian Giotto and can't find something that would support that. Or can it be done in FlashDevelop? I think this is very important.

toosmooth
04-06-2012, 01:54 PM
I'm having trouble with using fscommands in flash develop. Would the code for the button be the same as it is when using adobe flash after going into the actions menu?

Would I be able to type:
on (press)
{
fscommand("load map");
}

And then hook up the necessary nodes in kismet or is there more code to input into the FD file before I can call the fscommands through kismet?

Thanks in advance!

Sent from my Galaxy Nexus using Tapatalk

toosmooth
04-06-2012, 03:38 PM
Ok, I tried the above referenced code that Donald had mentioned in an earlier post and I'm getting the following error:

src/SnowballMainMenuVG.as:6: characters 0-6 : parse error Unexpected import

Here is my code:

class SnowballMainMenuVG
import flash.external.ExternalInterface;

{
static var vectorApp:SnowballMainMenuVG;
//serves as entry point
static function main(mc:MovieClip):Void
{
vectorApp = new SnowballMainMenuVG();
}
public function SnowballMainMenuVG()
{
Mouse.hide();
var mouseListener:Object = new Object();
mouseListener.onMouseMove = function()
{
//Set the cursor instance position to the mouse position
_root.cursor._x = _root._xmouse;
_root.cursor._y = _root._ymouse;
_root.exitBtn.onPress = function()
{
ExternalInterface.call("ExitClicked");
}

updateAfterEvent();
};

Mouse.addListener(mouseListener);
}
}

Any suggestions as to why i'm getting this compile error when everything was done exactly as stated in the tutorial?

isathar
04-06-2012, 03:53 PM
The error is caused by having imports inside your class. Move the import statement to be before the class declaration. My Actionscript 2 is a bit rusty, but at a glance the rest looks like it should work.

toosmooth
04-06-2012, 09:00 PM
That worked like a charm as far as getting the script to compile! I'm going to hook up the kismet work to see if it actually works when played in PIE or in game from the command line in visual studios.

Would I do something like what I have above to get the play game button to work or would I have to go another route and have it call Unrealscript externally in order to set up fscommands to play with?

I'm new to flash development but I'm liking it more and more as I see success when I try different things.

Thanks for the reply :)

Sent from my Galaxy Nexus using Tapatalk

milerk
05-30-2012, 02:56 PM
can we manage CLIK components not using Adobe Flash Professional somehow?
does it work with Vectorian Giotto?

NoxRequiem
09-27-2012, 03:20 AM
Sweet tutorial Donald dude, I'm so happy UDK has such a dedicated developer community XD

NoxRequiem
09-27-2012, 06:04 PM
Alright, so I'm using both flash develop and giotto. So far I got a png mouse working and my menu running when I start my test level.

My main is issue is that while debugging my button that's supposed to allow me close the menu I noticed how WidgetInitialized is never being called, here is my defaultproperties code where i add the widget

WidgetBindings.Add((WidgetName = "TestButton", WidgetClass = class'GFxCLIKWidget'))

I was wondering if anyone has found ways around this, I've also tried the externalinterface route through my flashdevelop code to an unfortunate dead end as well.

- is there something I can do in flashdevelop or giotto for unrealscript to know that my button is a widget or the fact that I made it a button already mean that it's a widget

MVGS
09-28-2012, 02:27 AM
Is it a button from the CLIK library? You'll have to manually set in your actionscript the callback flag:

MyWidget.enableInitCallback = true

NoxRequiem
09-28-2012, 01:50 PM
I'm not sure what you mean, so if my button is name TestButton in action script would i have to be like

_root.TestButton.enableInitCallback=true; ?

chameleonfx611
10-26-2012, 10:05 PM
Hey great looking tutorial! I couldn't find a gui and was just going to go with flash develop, but was fortunate enough to find this tutorial in a google search. I have one question though, why did you use flash develop at all? why didn't you just use the actionscript pane in Giotto to connect it to UDK!? Also have you done anything else with it and UDK?

chameleonfx611
10-26-2012, 10:24 PM
I think you need to get rid of the double parentheses. Try WidgetBindings.Add(WidgetName = "TestButton", WidgetClass = class'GFxCLIKWidget')




Alright, so I'm using both flash develop and giotto. So far I got a png mouse working and my menu running when I start my test level.

My main is issue is that while debugging my button that's supposed to allow me close the menu I noticed how WidgetInitialized is never being called, here is my defaultproperties code where i add the widget

WidgetBindings.Add((WidgetName = "TestButton", WidgetClass = class'GFxCLIKWidget'))

I was wondering if anyone has found ways around this, I've also tried the externalinterface route through my flashdevelop code to an unfortunate dead end as well.

- is there something I can do in flashdevelop or giotto for unrealscript to know that my button is a widget or the fact that I made it a button already mean that it's a widget

LeWiS NeWmAn
08-16-2013, 02:12 PM
Hi can you link me to any tutorials as i cannot find any

lewigi
09-11-2013, 12:13 PM
Hi there, my apologies to reawaken an old thread, but I'm having an issue and cannot pinpoint what's going wrong.

I followed your tutorial and got the menu and cursor working great! I'm trying to make the exit button simply call a method in my UScript that exits the game.
My actionscript:

import flash.external.*;
...
public function PreAlphaMenu()
{
var mouseListener:Object = new Object();

mouseListener.onMouseMove = function ()
{
//set the cursor to the mouse position
_root.cursor._x = _root._xmouse;
_root.cursor._y = _root._ymouse;
_root.exitBtn.enableInitCallback = true;
_root.exitBtn.onPress = function()
{
ExternalInterface.call("ExitClicked");
}
updateAfterEvent();
};
Mouse.addListener(mouseListener);
}


My Uscript:

class GfxMainMenu extends GfxMoviePlayer;

function ExitClicked()
{
local string command; //breakpoint here, the method never gets called and can't trace why.
`log("Callback Recieved");
command = "Exit";
ConsoleCommand(command);
}

defaultproperties
{
MovieInfo=SwfMovie'PreAlphaContent.PreAlphaMenu' //This is correct, have checked countless times
}

The most frustrating part is that I have no errors or warnings anywhere, the "ExternalInterface.call" part just doesn't seem to want to call the Uscript method. It seems to work for a everyone else fine and I can't see where I'm going wrong.
Awesome tutorial by the way, thank you very much :)

I solved it! Actually very simple solution and can't believe I missed it haha. For anybody else that has the same issue, you have to set the "Movie Player Class" under the properties of the "Open GFx Movie" node in kismet to the custom Uscript class.