In our pipeline, we ultimately publish HTML5 using Toolkit for CreateJS. However one of the steps to get us to that HTML5 includes publishing an SWF that outputs some Javascript code. I've mostly managed to automate this using JSFL. However, at present there is one line of AS3 that our artists have to find on the timeline and change manually, but it interrupts their workflow, and if they miss it or mess it up it is hard to catch, so I would like to automate it too:
Object(root).log.text += " root.skillAnime189 = factory();\n";
From the above, "skillAnime189.fla" is the name of the .fla file which contains this code. This is the case if the artist is working on Skill Animation #189, but if he is doing #304 or #6 or #1022 (no padding) the number changes accordingly, and he has to update that line accordingly.
So, I would like to change that line to something like:
var flaName:String = getThisFlashFileName().split(".")[0];
Object(root).log.text += " root." + flaName + " = factory();\n";
but I am at a loss as to how to access the name of the .fla file containing the code.
The common way to get the swf name is to parse stage.loaderInfo.url parameter:
var url:String = stage.loaderInfo.url;
url = url.split("?")[0]; //remove query string after "?"
var swfname:String = url.substring(url.lastIndexOf("/")+1);
trace(swfname);
output:
astest.swf
But this code gives swf but, rather than fla, so you need to maintain the same names for flas and published swfs (any case usually they are the same, so it shouldn't be the problem)
Related
I am building a program on Animate CC 2019 which needs to access a text file where it can read from and write to.
I want to store strings and numbers, from Input Texts, then write them in the file, in addition to the already existent contents.
I also need to be able to manage how the data is written in the file. So, for example, I want to have 2 arrays: Array1 stores names and Array2 stores numbers. So when the program writes to the file, it needs to write on each line the corresponding values of a specific index in the arrays. So if Array1(0) = name1 & Array2(0) = 52, in the file it should be written:
name1 52
If not exactly like this, a way which data can be written in a manageable way.
I am trying this on Windows 10/AIR.
My questions:
How can I manage how data are written in a file?
Which code should I use? I find info on two ways to approach this:
a. Code using “File” and “FileStream” which does NOT work! I get error messages: “Type was not found or was not a compile-time constant” for both, like the system does not recognize the commands. Are these commands still usable on the current version of Animate CC?
b. The code snipets/AIR code which does work, however, I cannot find a way to manage how data are written in the file, as explained above. Everytime something is written in the file, the previous data are overwritten.
Below the codesnipets code which works.
/* Click to Write to a Text File
Clicking on the specified object will prompt the user to select a location and file name and save a text string to it.
Instructions:
To set what data is saved to the file change "Text to save to file." to the data you wish to save.
*/
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
movieClip_1.addEventListener(MouseEvent.CLICK, fl_SaveFile);
var fl_FileDataToSave:String = "Text to save to file.";
var fl_SaveFileStream:FileStream = new FileStream(); // FileStream used to write to the file
var fl_SaveFileChooser:File = File.documentsDirectory; // Default to the documents directory
fl_SaveFileChooser.addEventListener(Event.SELECT, fl_WriteFileHandler);
// Opens a Save As dialog box for user to specify a file name
function fl_SaveFile(event:MouseEvent):void
{
fl_SaveFileChooser.browseForSave("Save As:");
}
// Write data in fl_FileDataToSave variable
function fl_WriteFileHandler(event:Event):void
{
fl_SaveFileChooser = event.target as File;
fl_SaveFileStream = new FileStream();
fl_SaveFileStream.openAsync(fl_SaveFileChooser, FileMode.WRITE);
fl_SaveFileStream.writeMultiByte(fl_FileDataToSave, File.systemCharset);
fl_SaveFileStream.close();
}
I have a quite simple programming question I was hoping somebody could help me with.
I'm working with Tiff files with several channels (all contained in a .lif file, which is Leica format). I want a way to easily convert all my Tiffs to Tiffs containing only a few of the channels (which I specify). Right now I'm doing it manually, for each image and it is tedious. I have no experience in writing macros and some help or a starting point would be much appreciated. I'm sure it's not a complicated macro to write.
As of now I'm using the following manual routine and commands after I have opened all my Tiffs:
Image > Stacks > Stack to Images - separates the stacked imaged into individual images
Close images I dont wan't to be in stack.
Image > Stacks > Images to Stack - Returns the remaining images to a stack and renames it.
Image > Hyperstacks > Stack to Hyperstack - here I change it so that the image has 3 channels.
Save the new Tiff with the desired channels and name.
Close the Tiff and repeat for all Tiffs.
What I want is a Macro that loops the above steps for all open Tiffs, letting the user specify the channels (eg. keep channels: 2,3 and 5). I know it's a very simple programming task, but I could really use some help getting it done.
Thanks!
Johannes
There are several less complex possibilities to create a stack with only a subset of channels:
Image > Stacks > Tools > Make Substack..., which lets you specify the channels/slices, and gets recorded as:
run("Make Substack...", "channels=1,3-5");
Image > Duplicate..., where you can select a continuous range of channels, such as:
run("Duplicate...", "duplicate channels=1-5");
To apply this procedure to all images in a folder, have a look at the Process Folder template in the Script Editor (Templates > IJ1 Macro > Process Folder) and at the documentation on the Fiji wiki:
Scripting toolbox
How to apply a common operation to a complete directory
Thanks for the help Jan Eglinger, back from vacation I managed to write the macro, which was simple with your help :) Based on the template it looks like this (I just gave them incremental names which is fine for my purpose, but could be made more allround i guess):
/*
* Macro to for converting multichannel Tiffs to Tiffs with only specified channels, processes multiple images in a folder
*/
input = getDirectory("Input directory");
output = getDirectory("Output directory");
Dialog.create("File type");
Dialog.addString("File suffix: ", ".tif", 5);
Dialog.show();
suffix = Dialog.getString();
processFolder(input);
function processFolder(input) {
list = getFileList(input);
for (i = 0; i < list.length; i++) {
if(File.isDirectory(input + list[i]))
processFolder("" + input + list[i]);
if(endsWith(list[i], suffix))
processFile(input, output, list[i]);
}
}
function processFile(input, output, file) {
open(input + file);
print("Processing: " + input + file);
run("Make Substack...", "channels=1,2,4"); //Specify which channels should be in the final tif
print("Saving to: " + output);
saveAs("Tiff", output + i);
close("*");
}
So I have a little flash app I made for an experiment where users interact with the app in a lab, and the lab logs the interactions.
The app currently traces a timestamp and a string when the user interacts, it's a useful little data log in the console:
trace(Object(root).my_date + ": User selected the cupcake.");
But I need to move away from using traces that show up in the debug console, because it won't work outside of the developer environment of Flash CS6.
I want to make a log, instead, in a SO ("Shared Object", the little locally saved Flash cookies.) Ya' know, one of these deals:
submit.addEventListener("mouseDown", sendData)
function sendData(evt:Event){
{
so = SharedObject.getLocal("experimentalflashcookieWOWCOOL")
so.data.Title = Title.text
so.data.Comments = Comments.text
so.data.Image = Image.text
so.flush()
}
I don't want to create any kind of architecture or server interaction, just append my timestamps and strings to an SO. Screw complexity! I intend to use all 100kb of the SO allocation with pride!
But I have absolutely no clue how to append data to the shared object. (Cough)
Any ideas how I could create a log file out of a shared object? I'll be logging about 200 lines per so it'd be awkward to generate new variable names for each line then save the variable after 4 hours of use. Appending to a single variable would be awesome.
You could just replace your so.data.Title line with this:
so.data.Title = (so.data.Title is String) ? so.data.Title + Title.text : Title.text; //check whether so.data.Title is a String, if it is append to it, if not, overwrite it/set it
Please consider not using capitalized first letter for instance names (as in Title). In Actionscript (and most C based languages) instance names / variables are usually written with lowercase first letter.
I've looked everywhere for this answer..but I am not quite sure on how to do it exactly...
I am making a Flash Game using Flash AS3...
I need options where user can save and load their progress..
can somebody give a step by step on how to do this please? I am very new to actionscript...
usually other tuts shows u how to save certain variables
Cookies!
Lucky us it's very simple. Unlucky us it's not obvious how it's done:
// have that referenced all the time:
var cookies: SharedObject = SharedObject.getLocal("myGameData");
// start saving
cookies.data.progress = 50;
cookies.data.lives = 5;
cookies.data.anyRandomVariable = "my name or something";
cookies.flush();
// now it's saved
// start loading
var progress: Number = cookies.data.progress;
var lives: int = cookies.data.lives = 5;
var anyRandomBlah: String = cookies.data.anyRandomVariable;
// now it's loaded
(following the comments above...)
Yes, pretty much along those lines. I was asking questions to try to get you to see that you do actually have variables/data which you'd save. =b
If you want to save in the middle of the level, it is up to you... I don't know how you've designed your game, but basically you can write the saving code to trigger whenever you want based on any conditions you want.
For saving in the middle of levels, since you are handling the saving and loading you could try having a value like level "7.5" or whatever notation you want to indicate a level that is partway done. Or just use whole numbers like 750 and treat it as a percentage (level 7 at 50% done). And so forth. It's up to you.
A very similar question has been asked how to save a current frame value using a SharedObject. In your case, replace 'current frame' with whatever values you want to save:
Actionscript 3 saving currentframe location to local hard drive?
I asked similar question sometime ago, but I am making new one to be much more specific with my question with some example!
I´ve found this code snippet/tutorial from googling, but I cant seem to figure out how to modify it for my needs:
// open a local shared object called "myStuff", if there is no such object - create a new one
var savedstuff:SharedObject = SharedObject.getLocal("myStuff");
// manage buttons
btnSave.addEventListener(MouseEvent.CLICK, SaveData);
btnLoad.addEventListener(MouseEvent.CLICK, LoadData);
function SaveData(MouseEvent){
savedstuff.data.username = nameField.text // changes var username in sharedobject
savedstuff.flush(); // saves data on hard drive
}
function LoadData(MouseEvent){
if(savedstuff.size>0){ // checks if there is something saved
nameField.text = savedstuff.data.username} // change field text to username variable
}
// if something was saved before, show it on start
if(savedstuff.size>0){
nameField.text = savedstuff.data.username}
So what I am trying to figure out how to do, is to save users current frame to local hard drive, as my flash progress is based on frame location. yeah, so how do I modify it so that it stores data of current frame? and how about current frame inside movieclip, if that is makes things different?
help MUUUCH appreciated! thanks!
In your example it looks like it is already saving something to the shared object:
savedstuff.data.username = nameField.text;
Just replace it with the movie clip frame value instead (and probably under a different property name other then "username").
Then on load, there is another line where it loads the data:
nameField.text = savedstuff.data.username;
It would be the same way, except replace "username" with whatever property name you choose. Then you may have to parse into an int again and use it to restore progress however way you have it set up.