ActionScript 3 Link to button resource using a string - actionscript-3

I'm trying to make an interactive quiz using Adobe Flash and AS3. On the scene, each question has 3 specific resources, for example:
question1_correct_btn
question1_incorrect_btn
question1_background
I don't want all resources for each question to be visible. How can I enable the visibility of the buttons, but instead of: 'question1_correct_btn.visible = false', I can do something like: ''question' + questionNum + '_correct_btn'.visible = false'' ?

You can access it like buttons_parent["question" + questionNum + "_correct_btn"].visible
I'd suggest checking that buttons_parent["question" + questionNum + "_correct_btn"] is not null before accessing its properties (to aviod error 1009 Null object reference) — just in case

You could use square brackets to access buttons, as #www0z0k suggests. However, I'd suggest you use DisplayObjectContainer.getChildByName(), as it is designed for this specific purpose: accessing children by name in a display list tree.
If the code in question resides directly in timeline of buttons' parent, you could just do getChildByName('question' + questionNum + '_correct_btn').visible = false;

Related

Using Chrome.ahk library to fill out a field inside an iframe

Hello can anybody help me with trying to edit a field inside an ifram using CHROME.ahk
The following code works when I create an IE ojbect. This is the part I use to fill in the field.
workoder := test
frame := pwb.document.parentWindow.frames("uxtabiframe-1068-frame")
frame.document.GetElementsByName("ff_workordernum").item[0].Value := workorder
How do I do this using the chrome.ahk library.
and it doesn't work. I have tried several methods. Can anybody please help
I have trid this:
PageInstance.Evaluate("document.parentWindow.frames('uxtabiframe-1068-frame').document.GetElementsByName('ff_workordernum').item[0].Value = 'test' )
I get an error. I tried
iframeJs =
(
var iframe = document.getElementById('uxtabiframe-1068-frame');
var test2 = iframe.contentDocument..GetElementsByName('ff_workordernum').item[0].Value = 'test';
)
PageInstance.Evaluate(iframeJs)
I believe the problem with the first try you are trying to get the property "document" of the Iframe here:
frames('uxtabiframe-1068-frame').document
However Iframes have no such property, it's called "contentDocument"
I think this is silly and confusing that it is like this, just "document" makes more sense and should be the standard.
Also in the first try there is an opening double quote but there isn't a closing one.
In the second try there is a repeated "." here:
iframe.contentDocument..GetElementsByName
You only need one of them.
And also with the second try you've tried to assign a variable over multiple lines, everything must be on the same line and you can do that by using "`n" which is an escaped newline character.

3ds Max TransNode not recognized as object

We're having some problems accessing the parent object (the TransNode) in our Forge viewer application. The TransNode is the object/node which contains all the materials used in the object.
Our research found that TransNodes are not recognized as objects by the Forge Viewer. We can still access its materials (Mat0, Mat1, Mat3 etc), but not the parent (the TransNode).
Would it be possible to define the TransNodes as objects in the API or is there any workaround we could use? Thanks a lot.
If in a 3ds Max scene, an object has applied a Multi-Material, upon translation, for each channel there will be created a subcomponent.
This becomes handy when you want to create selectable parts of a mesh, without breaking apart the mesh.
However, if you want to avoid this subcomponent selection and select the entire object upon subcomponent selection, there are 2 approaches:
At 3ds Max level, before translating the scene, replace the Multi-Material with a Basic/Single Material. To keep the texture/colour, just bake the MultiMat into a bitmap and use it as diffuse colour in the Basic Material.
At Forge Viewer level, you could tailor selection using algorithm like:
if I am selecting a child, select automatically the parent.
This is done by subscribing to selection event and at minimum, the code could look like this:
let viewer = viewerApp.getCurrentViewer();
let tree = viewer.model.getData().instanceTree;
viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT,
(event) => {
if (event.selections[] != undefined) {
let selectedNode = event.selections[0].dbIdArray[0];
console.log("selected a node with id = ", selectedNode);
if (tree.nodeAccess.getNumChildren(selectedNode) == 0) {
let parentId = tree.nodeAccess.getParentId(selectedNode);
console.log("parent of the selected node is ", parentId)
viewer.select(parentId);
}
}
})
Thus, any selection of a "leaf", will automatically select the parent of that "leaf" along with all that is under the parent node.
The second approach is derived from one of our blogpost discussing the idea of Controlling components selection in the Viewer.

AS3 Dynamic variable naming

Is dynamic variable naming like this possible in ActionScript 3?
for (var xz=0;xz<10;xz++){
var this['name' + xz]:Number = xz;
}
You should use an array for this kind of list of variables.
While you can create properties dynamically, you usually want to avoid it. Especially in your case, where the actual identifier of each variable is not a String, but a number. So why not use something that does exactly that: identify its elements by a number? And that's exactly what an array does.
code example:
var xzs:Array = [];
for (var xz:uint = 0; xz < 10; xz++){
xzs.push(xz);
}
Short answer is: no, you can't declare at runtime typed properties.
Long answer is: kinda.
If you want to create new typed properties you'll have to store them in a Vector<>.
Anything else would let you do it but untyped, dynamic class, store in object, store in array, etc ...
Yes, it sure is - AS3 comes from ECMA script, so this is setting a property to an object (in this case it's this). So you can dynamically set properties. But you are a little bit wrong about how to do it - there is no need to use var, because you don't declare it, you set it. It's like using:
this.propertyName = 'value';
From now on, this will have propertyName equal to 'value'. Therefore you should just use:
this['name' + xz] = xz;
That's all!
Edit: as BotMaster mentioned - if you are using classes and you want to dynamically add properties, the class must be set as dynamic. Most of the commonly used ones are already dynamic (as Aaron mentioned :)).
I didn't go into much details as I think you simply need to do this on your timeline. If not - please specify this in your question so that you can get more accurate answer than this one. The same goes if your new property needs to be typed (can't think of any point wanting this) - you should see BotMaster's answer :)

retrieving a variable value from lower level

well i created some variables in the main stage level, with something like this:
for(i=0,i<10,i++){
var var_name="var_num_"+i;
this[var_name]="some value";
}//<-----------------------------------------------------works
so i get 10 variables named "var_num0", "var_num1", "var_num2" each one with some value.
and i can acces them any where calling this
var second_var=MovieClip(root).var_num0;//<--------------works
my problem comes when i want to call all the variables from a lower level or in another frame or somewhere else using another loop:
var third_var;
for(j=0,j<3,j++){
third_var=this["MovieClip(root).var_num_"+j];//<---------DOSNT WORK
trace(this["MovieClip(root).var_num_"+j]);//<------------returns "undefined"
}
how can i make this work? i tried a lot of things and nothing...
thanks you all
In your case both "root" and "this" are the scope you want to access the vars from. so try this:
var third_var:MovieClip;
for(j = 0; j < 3; j++)
{
third_var = MovieClip(root)[var_num_ + j];
trace(third_var);
}
Also you should have semi-colons in your for loop rather than comers.
I'd like to preface my answer with a suggestion you use a 'Document Class' with AS3 to make things like namespaces and inheritance much clearer. You know exactly where things are accessible when using document based, object oriented programming versus the timeline programming available through the Flash IDE (its only there because of AS1/2). Tut: http://www.kirupa.com/forum/showthread.php?223798-ActionScript-3-Tip-of-the-Day/page14
On to the answer: You are trying to move two levels of inheritance in one set of [] Another way of writing your first "Doesn't work" line is:
this.myMovieClip["var_num"+j"];
You could also use: this["MovieClip"]["var_num"+j];
Basically, you need to take the "MovieClip(root)" out of the string you are using to call your variable because you are passing through two levels of inheritance: this->MovieClip->targetVar
You need to use two periods, a period and a set square bracket or two sets square brackets to move two levels of inheritance. A period . and a set of square brackets [] both accomplish the task of moving one level deeper, so putting the . inside the string used to call up your variable won't work.
Explanation:
The following three examples all return the same variable:
myMovieClip.my_variable
myMovieClip["my_variable"]
var str:String = "my_variable";
myMovieClip[str];

As3 - Assign class to object on stage

I think the title should make it pretty clear. I was wondering how you can assign a class to an object on stage. As you would do with actionscript:
var objectname:ClassName = new ClassName();
This would make a new object, but the current object already exists, it just needs to be notified that it's of the type "ClassName" so it can inherit it's properties.
I've also tried assigning the "ClassName" in the linkage as either the base path or the class name. But in either situations I get an error saying that the class needs to be unique when I use the same class on multiple objects.
So I would need something like
//example exists on stage
example.class = ClassName
Thanks
I will answer your question with a question : why are you assigning the same class on multiple objects?
If what you want is a common behavior for those objects, you should create your class and assign it has the Base Class on those objects.
I don't think there's a way to do just do that. But I do suggest you look into the decorator design pattern The idea here is that you don't change the class, but you "decorate it" with more functions as needed.
Hope this helps !
You seem to have this the wrong way around. You define a class in order to set specific behavior & properties for an object. In a real life example, if I want to build a radio , I will come up with a radio design & implement it. Now if I need several radios, I will use the same implementation to manufacture them.
If I now wish to turn my radio into a TV , I can't just tell my radio, hey , you're a TV now. I can either decide beforehand that I want a radio/tv object and switch behavior whenever necessary or I can create a new TV object and add the radio functionality to it by adding a radio component to my TV object.
var radio:Radio // your current object
//example 1
radio.switchToTv();
//example 2
var radioTv:Tv = new Tv( radio );