Why NSView animator doesn't work in Cocoa - cocoa

I have a NSView in my project that I want to move but the animation I usually use for other objects doesn't work with it... what should I do to make it move?
Here is my code:
[[NSAnimationContext currentContext] setDuration:1.0];
NSRect rect = NSMakeRect(59.0,10.0,682.0,575.0);
[[self.myView animator] setFrame: rect];

I found the way to make it work...
For some reason the animation was working if called alone but not working when called after an IAP...
I found out that calling the void with the animation with this line of code made it work:
[self performSelectorOnMainThread:#selector(myAnimation) withObject:nil waitUntilDone:NO];

Related

NSView resizing shaky

I have an MAAttachedWindow (subclass of NSWindow), which contains a blank view (contentView), and some arbitrary subview (right now an NSImageView).
On load, I'm attempting to resize the window by 100px vertically, in an animated fashion.
This code block initializes my window and views:
_popoverContentView = [[NSView alloc] initWithFrame: aFrame];
NSImageView *img = [[NSImageView alloc] initWithFrame: aFrame];
[img setImage: [NSImage imageName: "#my_debug_image"]];
[img setAutoresizingMask: NSViewHeighSizable];
[_popoverContentView setAutoresizesSubviews: YES];
[_popoverContentView addSubview: img];
popover = [[MAAttachedWindow alloc] initWithView: _popoverContentView attachedToPoint: aPoint inWindow: nil onSide: MAPositionBottom atDistance: aDist];
And this code block is responsible for the animation:
NSRect newPopoverFrame = popover.frame;
NSRect newPopoverContentViewFrame = _popoverContentView.frame;
newPopoverFrame.size.height += 100;
newPopoverContentViewFrame.size.height += 100;
[_popoverContentView animator] setFrame: newPopoverContentViewFrame];
[[popover animator] setFrame: newPopoverFrame display: YES animate: YES];
Now this all works (almost) as expect, however as shown in this video, the animation is unreliable, shaky, and jumpy. I can't seem to pinpoint what in my code is causing this, or how to go about locking the image view into place.
I think the problem is that you're using the new(ish) animator proxy to animate the window's frame while also using the much older animate: parameter of NSWindow's setFrame:display:animate:, which uses the old NSViewAnimation API.
These two animation methods are probably conflicting as they try to animate the window simultaneously using different code paths.
You also need to wrap multiple calls to the animator proxy in [NSAnimationContext beginGrouping] and [NSAnimationContext endGrouping] if you wish the animations to be simultaneous.
Try doing this:
[NSAnimationContext beginGrouping];
[_popoverContentView animator] setFrame: newPopoverContentViewFrame];
[[popover animator] setFrame: newPopoverFrame display: YES animate:NO];
[NSAnimationContext endGrouping];
If that doesn't work, you could drop the use of the problematic setFrame:display:animate: method and just animate the position and size independently:
[NSAnimationContext beginGrouping];
[_popoverContentView animator] setFrame: newPopoverContentViewFrame];
[[popover animator] setFrameOrigin: newPopoverFrame.origin];
[[popover animator] setFrameSize: newPopoverFrame.size];
[NSAnimationContext endGrouping];
The animation context grouping will ensure that everything happens simultaneously.

Lion compound animations for full screen

I'm transitioning a window to full screen mode (the new Lion kind of full screen mode). While I do the transition, I'd like to also slide one of the views in my NSWindow to a new position.
So, in my NSWindowDelegate, I've tried returning the window and implementing the custom animation:
- (NSArray *)customWindowsToEnterFullScreenForWindow:(NSWindow *)window
{
return [NSArray arrayWithObject: window];
}
- (void)window:(NSWindow *)_window startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration
{
// book is NSView *ivar
[[book animator] setFrame: NSMakeRect(/*computed rect*/)];
}
But this completely kills the default animation of going to full-screen mode and my window suddenly doesn't paint correctly.
Is there some way to compound these while still using the default animation? I'm pretty new to core animation beyond [view animator] level stuff, So I'm sure I'm screwing up something quite simple.
You have to write something like this in order to have the two animations in sync:
- (void)window:(NSWindow *)_window startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration
{
// book is NSView *ivar
[[NSAnimationContext currentContext] setDuration:duration];
[[book animator] setFrame: NSMakeRect(/*computed rect*/)];
}

Cocoa NSView not filling with color

What am I doing wrong?
I have an awakeFromNib method in which I am calling a class that is a subview (GameMap). The class exists and I am able to log in the awakeFromNib method as well as log in GameMap's initWithFrame method, but I cannot get GameMap to draw in the window. Here's my AppController.m file's awakeFromNib method:
-(void) awakeFromNib {
//make new game map
GameMap* newMap = [[GameMap alloc] initWithFrame:NSMakeRect(0.0, 0.0, 1000.0, 500.0)];
[[[NSApp mainWindow] contentView]addSubview:newMap];
[newMap release];
}
and in GameMap.m here's the drawRect method
- (void)drawRect:(NSRect)rect {
[[NSColor whiteColor] set];
NSRectFillUsingOperation(rect, NSCompositeSourceOver);
}
in this same app I am calling two other classes from AppController, all subviews of NSView, MakeCircle and MakeRoom that place either a circle (duh, : D) or a rect with a stroke in the window and they work fine, but they are running off of IBOutlet actions (button clicks). Any help would be appreciated.
*NOTE: I have NSRectFillUsingOperation(rect, NSCompositeSourceOver) but this was also failing wiht NSRectFill(rect).
**I can also log the origin.x/size.width, etc. of the passed rect to GameMap from the initWithFrame, so I know it's there.
(I'm away from my computer for a few hours so don't think I'm being rude for not replying, just wanted to get this question out there before I left.)
Just use NSRectFill(rect); instead of NSRectFillUsingOperation(rect, NSCompositeSourceOver);
Have you set the view's class to the GameMap class instead of NSView) in the Interface Builder? When you do this, the GameMap's drawRect() should get called automatically.

Animator of NSView does not animate alpha value change

I've got a problem handling the animators of NSViews.
In the code below I create a (custom) controller which also has got a view. I want it to fade it into the window, and fade the old one out. But it doesn't animate at all, the new view just appears, and the old one gets "removeFromSuperview" instantly.
Also, I have seen that the old view behaves normally, it fades out. But the new one is in the way and doesn't fade at all.
My code:
LTController *newController=[[LTController alloc] init]];
[[newController view] aFrame];
[[newController view] setAlphaValue:0];
[[[self window] contentView] addSubview:[newController view]];
[[[newController view] animator] setAlphaValue:1];
[[[viewController view] animator] setAlphaValue:0];
[viewController view] performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:[[NSAnimationContext currentContext] duration]];
[self setViewController:newController];
How can it be that the animator doesn't do anything to animate? What am I doing wrong?
Thanks in before,
Ivorius
You need to set your views as Layer backed for this to animate

CoreAnimation doesn't work with -setAlphaValue on QTMovieView

I have some basic code for adding a QTMovieView. I want it to fade in, so I add an animation on setAlphaValue. Only issue is that it doesn't work. The alpha value is instantly set to whatever it was supposed to animate to. If I try animating e.g. setFrame: it works fine. You'll find my code below. This is on 10.5.7 with the Mac OS X 10.5 SDK.
- (void)addMovie:(NSString *)aFile
{
QTMovieView *aMovieView;
QTMovie *aMovie;
NSRect contentFrame;
contentFrame = [[self contentView] frame];
aMovieView = [[QTMovieView alloc]
initWithFrame:contentFrame];
[aMovieView setWantsLayer:YES];
[aMovieView setControllerVisible:NO];
[aMovieView setPreservesAspectRatio:YES];
aMovie = [[QTMovie alloc]
initWithFile:aFile error:nil];
[aMovieView setMovie:aMovie];
[aMovieView setAlphaValue:0.4];
[[self contentView] addSubview:aMovieView];
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:2.0];
[[aMovieView animator] setAlphaValue:0.9];
[NSAnimationContext endGrouping];
}
Any ideas?
I don't know for sure but it sounds like QTMovieView may not support alpha compositing. One further test I would try would be to call setWantsLayer on the superview of the QTMovieView to see if that affects the QTMovieViews ability to composite correctly. Probably will not work.
You could try using QTMovieLayer instead. One way to incorporate QTMovieLayer would be to make your own NSView subclass that created and managed a QTMovieLayer that was added inside its root layer. Be aware though that when mixing layer backed views with non layer backed views in the same window you may get funny ordering if the layer backed views are not all in front or are behind and overlapping.
I suggest NSViewAnimation. It's a subclass of NSAnimation that will do the fading in and out for you.
I began on QTMovieLayer, but being less powerfull (of course) than QTMovieView it opened another box of issues. The solution was to use NSAnimation on the QTMovieView. I have a NSAnimation class looking somewhat like this:
AlphaAnimation.h
#import <Cocoa/Cocoa.h>
NSString * const AAFadeIn;
NSString * const AAFadeOut;
#interface AlphaAnimation : NSAnimation {
NSView *animatedObject;
NSString *effect;
}
- (id)initWithDuration:(NSTimeInterval)duration effect:(NSString *)effect object:(NSView *)object;
#end
AlphaAnimation.m
#import "AlphaAnimation.h"
NSString * const AAFadeIn = #"AAFadeIn";
NSString * const AAFadeOut = #"AAFadeOut";
#implementation AlphaAnimation
- (id)initWithDuration:(NSTimeInterval)aDuration effect:(NSString *)anEffect object:(NSView *)anObject
{
self = [super initWithDuration:aDuration animationCurve:0];
if (self) {
animatedObject = anObject;
effect = anEffect;
}
return self;
}
- (void)setCurrentProgress:(NSAnimationProgress)progress
{
if ([effect isEqual:AAFadeIn])
[animatedObject setAlphaValue:progress];
else
[animatedObject setAlphaValue:1 - progress];
}
#end
Which can then be used like this:
animation = [[AlphaAnimation alloc] initWithDuration:0.5 effect:AAFadeIn object:movieView];
[animation setAnimationBlockingMode:NSAnimationNonblocking];
[animation startAnimation];
If your QTMovieViews are in full screen it isn't very smooth, though.

Resources