Say I have a movieclip and within this movieclip I define some Actionscript variables. e.g.
var majorValue:Number = 20;
var minorValue:Number = 10;
By default, every instance of this movieclip on the stage will have these variables, set to these values. Now, lets say I have three instances of this movieclip on the stage, which I'll call "Moe", "Larry" and "Curly". Let's say I want to leave Moe and Larry as default instances of the movieclip, but I want to tweak the "Curly" instance so that it's majorValue is 50, and it's minorValue is 15. How do I go about doing this?
I've tried doing it by specifying:
Curly.majorValue = 50;
Curly.minorValue = 15;
In the parent timeline, but this doesn't seem to work as it seems the actionscript is executed in the parent clip first and then in the child(ren) clip(s) second. So in other words, my declaration of the "Curly" instance's special values is overridden by the clip's default declarations, which are executed after the parent clip's actionscript.
Does anyone know how to override a movieclip's default variables for a specific instance?
There's an old tip about working with the timeline which says, "if in doubt, add a key-frame". Actually, even better advice would be to avoid using the timeline altogether if at all possible.
I think your summation of what is happening is probably about right. In effect, you're trying to update the properties on the instance before it has been instantiated properly. When it is instantiated, the values are reset to the defaults.
The solution is to add an additional frame and place the code which sets the properties on the instance in the second frame (along with a stop action). This will ensure that the code is executed after the instance has been instantiated.
Related
Do you see any way to know when ANY model’s property has been modified through a binding?
I would need something generic because it would be applied to all the forms of the application. This means I cannot just have a 'property’Changed() observable callback for every properties of the models. I’m thinking along the ways of overriding the properties setters created by the binding engine so they can call a single defined callback but I feel like there could be a better way.
I created a aurelia-plugin for this kind of scenario (and more).
Its not exactly what your asking for, but can help you a lot.
because the plugin will create a single property called isDirty that you can observe and fire your code accordingly.
https://github.com/avrahamcool/aleph1-aurelia-utilities
look at the Dirty Tracking a model: section
your model class need to extends the baseClass provided by the plugin.
now you can decorate any properties of your model with the
#dirtyTrack() decorator.
for babel users: the assignment in the declaration will set the
default value for the property. for TS users: you should call the
decorator with a parameter #dirtyTrack(7) someInt: number;
this will set up a isDirty variable in your model. this property will
be automatically updated to with every change to your tracked
properties.
at any point, you can call saveChanges() on your model, to commit the
current changes. or discardChanges() to revert back to the last saved
point. you can call serialize() to get a pojo object from your model,
or deserialize(pojo) to populate your model from a pojo object.
Ok, I ended up just using the binding engine to watch all properties changes. This allowed me to implement my isDirty checks without modifying the existing models...
So the final code looks like this:
Object.getOwnPropertyNames(obj).forEach(p => {
this.subscriptions.push(this.binding.propertyObserver(obj, p)
.subscribe(() => this.updateDirty()));
});
my updateDirty() method is called after every property change and no change was necessary to the model.
If anyone can come up with a better solution, I'm still interested but this fits my needs for the time being.
I cant get my head around this. I was looking at the lynda.com ActionScript 3.0 in Flash Professional CS5 Essential Training. I understand all the other stuff, but this guy places a skater on the stage he has this code on the first frame on the main timeline:
import flash.display.MovieClip;
import flash.events.MouseEvent;
var boarder:MovieClip = boarder_mc;
boarder.stop();
boarder.x = 0;
boarder.y = 0;
boarder.addEventListener(MouseEvent.CLICK, clickedBoarder);
function clickedBoarder(evt:MouseEvent):void
{
boarder.gotoAndPlay(2);
}
function restart():void
{
boarder_mc.gotoAndStop(1);
boarder_mc.x = 0;
}
then on the skater he has a Display Object Container (Movie Clip) in it he has a Display Object a bitmap image of a skater and then an animation on the timeline in the skater where at the end the skater falls. On that last frame he has:
stop();
parent.restart();
He explains that this may not work and it doesnt he gets an error:
1061: Call to a possibly undefined method restart through a reference with static type flash.display:DisplayObjectContainer.
He explains that it knows there is a stop() function on the main timeline, and that it knows there is a restart function on the main timeline, but the datatype is different. He also says that the parent is the main timeline.
He says that we need to put Object(parent).restart();
My question is of what datatype and what is the main timeline (Movieclip, DisplayObject, Display Object Container)?
Why would it be a different datatype?
Thanks
The main timeline is a MovieClip, or if you have a DocumentClass, then probably a custom type that at least extends MovieClip.
However when you ask for "parent" of your skater MovieClip, you are really using the parent property that MovieClip inherits from DisplayObject (ActionScript Docs Here). This property returns the parent as type DisplayObjectContainer, regardless of the type that it actually is. Since it is the parent of a DisplayObject, it doesn't matter type it is it has to extend DisplayObjectContainer, so this is how it is returned.
So when you compile your ActionScript, the compiler looks at "parent" and sees it as type DisplayObjectContainer, looks at its definition of DisplayObjectContainer and errors because DisplayObjectContainer doesn't have a function called "restart".
What you said about the "stop" function is not really correct, since you are not calling stop on the main timeline, your are calling stop on the Skater's timeline. If you wanted to call stop on the main timeline you would need to call parent.stop(), and this would give you the same error, since DisplayObjectContainer doesn't have a method called stop.
These are both compiler errors, and are caused because the compiler is following a set of rules, and it can't make assumptions about what might actually happen when your program is running. It just knows that when you call parent.restart() it might receive a DisplayObjectContainer that won't have the method restart on it, and a run-time error will occur.
Now, by casting parent as type object, you are effectively telling that compiler that this thing can have any method or property on it, since Object is a dynamic class. So the compiler will now assume that you as the developer know that the method "restart" will exists on the "Object" that is given to that bit of code, and therefor will not error any more.
Thank you very much for you reply. This is really confusing. I thought that DisplayObjectContainer is a subclass of Display Object and it extends it? I know that Display Object Container is a Display Object and it can contain other Display objects and Display Object Containers. So the way I understand it, the maintimeline is a movieclip and therefore a DisplayObejctContainer, which can contain other Display objects (that you create in you application) and that is why parent returns Display Object Container, but that it is also a abstract class which means that it cannot have methods such as .restart and goToAndPlay() because it cannot actually be instantiated. However if its a MovieClip as you say then it can..... I dont get it.Does it mean that it is an abstract Class?
I have an Polymer.dart element with multiple attributes, e.g.
<code-mirror lines="{{lines}}" widgets="{{widgets}}">
</code-mirror>
on some occasions lines and widgets change simultaneously sometimes only widgets changes.
I would like to rerender component once independently on how many properties change in the same turn of event loop.
Is there a way a good built-in way to achieve that?
Additional trouble here is that interpretation of widgets depends on content of lines and ordering in which linesChanged and widgetsChanged callbacks arrive is browser dependent, e.g. on Firefox widgetsChanged arrives first before linesChanged and component enters inconsistent state if I do any state management in the linesChanged callback.
Right now I use an auxiliary class like this:
class Task {
final _callback;
var _task;
Task(this._callback);
schedule() {
if (_task == null) {
_task = new async.Timer(const Duration(milliseconds: 50), () {
_task = null;
_callback();
});
}
}
}
final renderTask = new Task(this._render);
linesChanged() => renderTask.schedule();
widgetsChanged() => renderTask.schedule();
but this looks pretty broken. Maybe my Polymer element is architectured incorrectly (i.e. I have two attributes with widgets depending on lines)?
*Changed methods are definitely the right way to approach the problem. However, you're trying to force synchronicity in an async delivery system. Generally we encourage folks to observe property changes and react to them and not rely on methods being called in a specific order.
One thing you could use is an observe block. In that way, you could define a single callback for the two properties and react accordingly:
http://www.polymer-project.org/docs/polymer/polymer.html#observeblock
Polymer's data binding system does the least amount of work possible to rerender DOM. With the addition of Object.observe(), it's even faster. I'd have to see more about your element to understand what needs rendering but you might be creating a premature optimization.
I think there are three possible solutions:
See this: http://jsbin.com/nilim/3/edit
Use an observe block with one callback for multiple attributes (the callback will only be called once)
Create an additional attribute (i.e. isRender) that is set by the other two attributes (lines and widgets). Add a ChangeWatcher (i.e. isRenderChanged() in which you call your expensive render method)
Specify a flag (i.e. autoUpdate) that can be set to true or false. When autoUpdate = false you have to call the render method manually. If it is set to true then render() will be called automatically.
The disadvantage of solution 1 is that you can only have one behavior for all observed attributes. Sometimes you want to do different things when you set a specific attribute (i.e. size) before you call render. That's not possible with solution 1.
I don't think there is a better way. You may omit the 50ms delay (just Timer.run(() {...});) as the job gets scheduled behind the ongoing property changes anyway (my experience, not 100% sure though)
I an confused about how to pass values of variables from 1 gamecomponent to another.
I am using xna 4.0.
I created two gamecomponents, the drawstring and the inputmanager.
I want to read the keyboard input of the user and pass it onto drawstring where it will update the position.
I cant add components on drawstring(drawablegamecomponent).
I can do it on class but not on gamecomponent.
Can you guys post some examples here. For beginners.
Use GameComponent for something that you would want to have Update called on every frame, and use DrawableGameComponent for something that you would want to have Draw called on every frame and LoadContent called when appropriate (at the start of the program, as well as whenever the device is lost, like when the user pressed Ctrl-Alt-Del on Windows).
For InputManager you might want an Update method, so that you can keep user input updated, so InputManager could be a GameComponent. DrawString doesn't sound like it needs to be. Both classes sound like they could be services. In the constructor or Initialize method of your game class, do something like the following:
Components.Add(mInputManager = new InputManager(this));
Services.AddService(typeof(InputManager), mInputManager);
Services.AddService(typeof(DrawString), mDrawString = new DrawString(this))
(DrawString and any other class that you want to get game services from will need a reference to the Game object.)
(Note that GameComponents do not necessarily need to be services, and services do not need necessarily need to be GameComponents. To get Update and/or Draw to be called, you must call Components.Add(...); separately, to get an object to be retrievable as a service, you must call Services.AddService(...)).
Then, when you would like to use the InputManager or DrawString service in some other game component (or any class that you have passed a reference to your game object), you can do this:
InputManager input = (InputManager)Game.Services.GetService(typeof(InputManager));
Personally, I write an extension method to make that more concise:
using XNAGame = Microsoft.XNA.Framework.Game;
...
public static T GetService<T>(this XNAGame pXNAGame)
{
return (T)pXNAGame.Services.GetService(typeof(T));
}
The line to get the input service then becomes:
InputManager input = Game.GetService<InputManager>();
I have several custom VCL components that do important tasks in their override of the TComponent Loaded() method. This creates a nuisance when creating instances dynamically since the Loaded() method is not called by the Delphi global loader during run-time, like it does for components that were placed on forms/frames at design-time. I also have to place the Loaded override in the public section of the class declaration so whatever code that creates an instance of the component can call it. Finally I have to remember to call Loaded() for dynamically created instances or subtle bugs will creep into the application, a problem that has bit me several times already.
Is there a better solution or approach to this?
If you need to call Loaded in your code you're doing it wrong. If you depend on a third party control that does, then I would fix that person's control. See below for how.
Let me make up a hypothetical example: Suppose I had 5 published properties, which once they are all loaded, can generate a complex curve or even better, generate a fractal, something that takes a long time.
At designtime I want to preview this curve, as soon as it's loaded, but I don't want the curve to be recalculated 5 times during DFM streaming, because each parameter P1 through P5 (type Double) has a SetP1 method, which invokes a protected method called Changed, and rebuilds my curve. Instead I have the SetP1 method return if csDesigning or csLoading are in the component states, and I then invoke Changed once, from Loaded. Clearly I can't rely on property setter methods alone, in all cases, to invoke all changes. So I need Loaded to tell me to do my first generation of some expensive work, that I want to be done 1 time exactly, not N times, where N is the number of DFM properties that would have been loaded that had method set procedures that invoked a method named Changed or something like that.
In your case, at runtime, you should not be relying on Loaded getting invoked at all. You should be instead, having your property set methods call Changed. If you need some way to change multiple properties at once, and then do some expensive thing only once, then implement a TMyComponent.BeginUpdate/TMyComponent.EndUpdate type of method call, and avoid extra work.
I can think of NO useful places where doing something from Loaded makes any sense, except for cases like the ones above, which should be specific to designtime and DFM based class use. I would expect a properly designed TComponent or TControl to properly initialize itself merely by being created in code, and by having its properties set.
So for my hypothetical TMyFractal component, I would do this when creating it in code without it ever having used DFM loading, or invoking Loaded:
cs := TMyFractal.Create(Self);
cs.Parent := Self; {Parent to a form}
cs.Align := alClient;
cs.BeginUpdate;
cs.P1 := 1.03; // does NOT trigger Regenerate
cs.P2 := 2.3;
cs.P3 := 2.4;
cs.P4 := 2.5;
cs.EndUpdate; // triggers expensive Regenerate method .
cs.Show;
// later someone wants to tweak only one parameter and I don't want to make them
// call regenerate:
cs.P5 := 3.0; // Each param change regenerates the whole curve when not loading or in a beginupdate block.
In my TMyFractal.Change method, I would invoke the expensive RegenerateCurve method once, each time any coefficient P1-P4 is modified at runtime, after initial setup, and once exactly when the component is streamed in from DFM, where Loaded is only used to handle the fact that I can hardly expect to do a beginupdate/endupdate in my control like I would have done in the code above.