Morphic Animation II
stephan.wessels at sdrc.com
Mon Mar 20 19:32:04 UTC 2000
I must be missing something. The e-mail message does not contain the class
definition for LaunchAlignmentMorph but the swiki does, so that's not too bad.
However, I have had no luck finding the class method
Jim Benson wrote:
> Here is my Morphic Animation example. Please read through it and comment.
> These are also available on the Swiki in what I think is an easier to read
> Jim Benson
> When we last left our hero, PathRectangleMorph was busily fighting the
> forces of evil, preparing the way for all that is good. He had fought
> himself into a corner and was waiting to be rescued. Here comes the
> LaunchAlignmentMorph to the rescue.
> LaunchAlignmentMorph instance methods:
> animateWindowOpening: theWindow inWorld: theWorld
> | topWindow anime |
> topWindow _ theWorld firstSubmorph.
> topWindow ifNotNil: [
> anime _ PathRectangleMorph beginPoint: ( topWindow bounds center )
> finishRectangle: ( theWindow bounds).
> anime setProperty: #sender toValue: self.
> anime startStepping.
> ifNil: [ self doneAnimation ].
> " add the world to the window "
> world addMorph: window.
> " and make the window the frontmost one "
> window activate.
> " Make sure that the submorphs are happening "
> world startSteppingSubmorphsOf: window.
> openInWindowLabeled: aString inWorld: theWorld
> | extent |
> inset _ 0.
> world _ theWorld.
> window _ (SystemWindow labelled: aString) model: nil.
> " guess at initial extent"
> bounds: (RealEstateAgent initialFrameFor: window initialExtent: self
> fullBounds extent);
> addMorph: self frame: (0 at 0 extent: 1 at 1);
> " calculate extent after adding in case any size related attributes were
> changed. Use
> fullBounds in order to trigger re-layout of layout morphs"
> extent _ self fullBounds extent +
> (window borderWidth at window labelHeight) + window borderWidth.
> window extent: extent.
> self animateWindowOpening: window inWorld: theWorld.
> So here it is. I've been talking all along about cool this, cool that, blah
> blah blah blah blah.
> Execute this in a Workspace:
> LaunchAlignmentMorph openLauncher
> I've tried to tell you, but you wouldn't listen. "He's on drugs, he doesn't
> know what's up!" Now you've seen it. That's way cool stuff. You open a
> window, and it just doesn't leap up on the screen. Instead the window
> appears to actually appear from somewhere. You can do this three or four
> times, and the windows show up in different places. Execute the same
> statement from another location on the screen. Play around with it some and
> see what it does. You can change the location that the animation starts at
> in the method #animateWindowOpening:inWorld: For example, you could start at
> the center of the screen by changing: anime _ PathRectangleMorph beginPoint:
> ( World bounds center ) finishRectangle: ( theWindow bounds).
> This technique is called temporal aliasing. For those interested in this
> kind of stuff, there is an excellent article called "Animation: From
> Cartoons to the User Interface" by Bay-Wei Chang and David Ungar. Ungar was
> one of the creators of the language Self, the environment where Morphic was
> first implemented. This article can be found in the "Proceedings of the ACM
> Symposium on User Interface software and Technology,[UIST] 1993, pg. 45".
> Hey, I don't name these things, I just read 'em. When I first read that
> article I remember thinking, "Who are those guys?" and, "Why can't I do
> things like that?". Well, they had Morphic even back then. That made them
> all powerful. They also had real machines, I had toys in comparison. Those
> guys also told me I needed to use an arc to animate this correctly. They're
> smart, I believe them. That's why you've had to put up with all that
> Arc/Path nonsense.
> There is one tricky part I'd like to talk about. Remember, I'm telling you
> right up front, this is tricky. But if you can master the following, you're
> well on your way to being the master of all you survey.
> When we're getting ready to start the animation we:
> anime setProperty: #sender toValue: self.
> It's not immediately obvious what this does. Morphs have something called
> properties You can think of properties (some people call them slots) as
> extra pockets that a Morph has to carry stuff around in. So we tell the
> Morph that we're calling anime to put 'self' (which is a
> LaunchAlignmentMorph) into a pocket named #sender. #sender is an instance of
> Symbol, which is a fancy kind of String.
> You're thinking, "I know this trick. This dude starts talking like this
> right before he hits me on the side of the head with more of that high
> falutin' computer jock junk". You know me all too well. Except I'm going to
> beat you upside the head a couple of times. I can control the power of
> Morphic, that gives me unbelievable strength and power.
> If we look at the code for PathRectangleMorph #stopStepping, towards the end
> we see:
> sender _ self valueOfProperty: #sender.
> sender ifNotNil: [ sender doneAnimation].
> We read this code as, "If I have a property called sender, send the message
> #doneAnimation to the value of the property named sender". After reading
> that last sentence, you can understand why people came up with programming
> languages. English just doesn't cut it. The code is easier to read than the
> description. I guess that's why we don't comment the code either.
> So why would we do something silly like that? Here's what we want to happen.
> The LaunchAlignmentMorph gets ready to open a window. It tells the
> PathRectangleMorph to show it's animation starting from the center of the
> window where we're currently at to the top left hand corner of the window
> that we want to open. When the animation is over, we open the
> LaunchAlignmentMorph window.
> 'All good and well', you say. 'Simple'. 'Straight forward'. 'Why is he going
> to mess with something as simple as that?' The simple answer is that now we
> can harness the power of Morphic for all that is good. Right here, right
> We coded our example to do this: When it is ready to open a window, the
> LaunchAlignmentMorph tells the PathRectangleMorph to start animating. Then
> the LaunchAlignmentMorph is out of it. Doesn't care about life anymore.
> Then, when the PathRectangleMorph ends its animation sequence, it sends
> #doneAnimation to the LaunchAlignmentMorph. So during the animation
> sequence, LaunchAlignmentMorph was free to go about its business, and do
> whatever it wanted to. This process is called by computer nerds, now get
> this, an asynchrounous callback. Catchy huh? These are the same people who
> brought you "http://". Do you find it surprising that they are the hit of
> every party?
> I'll give you an analogy. Let's say you want a pizza. You go to the pizza
> place, order a pizza, sit around 20 minutes, get the pizza, and take it
> home. Computer idiots call this a synchronous process. You start a task and
> follow through with it until the task ends.
> You could have done it differently. You could have called the pizza place on
> the phone, and ordered the pizza for delivery. Then you could have played
> your guitar, washed the car, and scared the neighbors cat before the
> delivery guy brought the pizza to your door. You had the amount of time
> between when you ordered and when the pizza was delivered free to do
> whatever you wanted. That's an asynchronous process.
> As you have figured out by now, that's how we can all sorts of animations
> going on at once. We basically just start 'em up and let 'em rip. Plus, they
> have a way to tell someone who is interested that they are done.
More information about the Squeak-dev