Edit: ich statt der langen Erklärung annehmen, unter ich auch könnte fragen: -setNeedsDisplay
auf eine Instanz CAEAGLLayer
Senden der Schicht nicht dazu führt, neu zu zeichnen (das heißt, wird -drawInContext:
nicht genannt). Stattdessen habe ich diese Konsole Meldung:Marrying Core Animation mit OpenGL ES
<GLLayer: 0x4d500b0>: calling -display has no effect.
Gibt es eine Möglichkeit, um dieses Problem? Kann ich -drawInContext:
aufrufen, wenn -setNeedsDisplay
aufgerufen wird? Lange Erklärung unten:
Ich habe eine OpenGL-Szene, die ich mit Core Animation Animationen animieren möchte.
Nach dem Standardansatz, benutzerdefinierte Eigenschaften in einem CALayer zu animieren, habe ich eine Unterklasse von CAEAGLLayer
erstellt und eine Eigenschaft sceneCenterPoint
darin definiert, deren Wert animiert werden soll. Meine Schicht hält auch einen Verweis auf die OpenGL-Renderer:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "ES2Renderer.h"
@interface GLLayer : CAEAGLLayer
{
ES2Renderer *renderer;
}
@property (nonatomic, retain) ES2Renderer *renderer;
@property (nonatomic, assign) CGPoint sceneCenterPoint;
ich die Eigenschaft @dynamic
dann erklären die Accessoren lassen CA erstellen, außer Kraft setzen +needsDisplayForKey:
und implementieren -drawInContext:
den aktuellen Wert der sceneCenterPoint
Eigenschaft an den Renderer zu übergeben und sie bitten es um die Szene zu machen:
#import "GLLayer.h"
@implementation GLLayer
@synthesize renderer;
@dynamic sceneCenterPoint;
+ (BOOL) needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:@"sceneCenterPoint"]) {
return YES;
} else {
return [super needsDisplayForKey:key];
}
}
- (void) drawInContext:(CGContextRef)ctx
{
self.renderer.centerPoint = self.sceneCenterPoint;
[self.renderer render];
}
...
(Wenn Sie den Zugriff auf die WWDC 2009 Sitzungs Videos haben, können Sie diese Technik in Session 303 ("Animated Drawing") bewertet).
Nun, wenn ich eine explizite Animation für die Schicht auf dem @"sceneCenterPoint"
keyPath erstellen, Core Animation soll die interpolierten Werte für die benutzerdefinierten Eigenschaften berechnen und -drawInContext:
der Animation für jeden Schritt rufen:
- (IBAction)animateButtonTapped:(id)sender
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sceneCenterPoint"];
animation.duration = 1.0;
animation.fromValue = [NSValue valueWithCGPoint:CGPointZero];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0f, 1.0f)];
[self.glView.layer addAnimation:animation forKey:nil];
}
Mindestens das würde für eine normale Unterklasse CALayer
passieren. Wenn ich CAEAGLLayer
Unterklasse, erhalte ich diese Ausgabe auf der Konsole für jeden Schritt der Animation:
2010-12-21 13:59:22.180 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect. 2010-12-21 13:59:22.198 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect. 2010-12-21 13:59:22.216 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect. 2010-12-21 13:59:22.233 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect. ...
So scheint es, dass, möglicherweise aus Leistungsgründen für OpenGL Schichten wird -drawInContext:
nicht, weil immer genannt Diese Ebenen verwenden nicht die Standardmethode -display
, um sich selbst zu zeichnen. Kann das jemand bestätigen? Gibt es einen Weg dahin?
Oder kann ich nicht die Technik verwenden, die ich oben dargelegt habe? Das würde bedeuten, dass ich die Animationen manuell im OpenGL-Renderer implementieren müsste (was möglich ist, aber nicht als elegantes IMO).
Danke für den Vorschlag. Ich werde es ausprobieren und melden. –
Es funktioniert in der Tat, vielen Dank! Die Leistung scheint nicht so gut zu sein wie eine reine OpenGL-Lösung, aber ich werde bald einen Blogbeitrag über die Details schreiben. –