Editar: supongo en lugar de la larga explicación a continuación También podría preguntar: Envío de -setNeedsDisplay
a una instancia de CAEAGLLayer
no causa la capa para volver a dibujar (es decir, -drawInContext:
no se llama). En su lugar, me sale este mensaje de la consola:Casarse Core Animation con OpenGL ES
<GLLayer: 0x4d500b0>: calling -display has no effect.
¿Hay alguna forma de evitar este problema? ¿Puedo invocar -drawInContext:
cuando se llama al -setNeedsDisplay
? Larga explicación a continuación:
tengo una escena OpenGL que me gustaría para animar el uso de animaciones Core Animation.
Siguiendo el enfoque estándar para animar propiedades personalizadas en un CALayer, creé una subclase de CAEAGLLayer
y definí una propiedad sceneCenterPoint
en ella cuyo valor debe ser animado. Mi capa también contiene una referencia al procesador OpenGL:
#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;
continuación, declaro la propiedad @dynamic
dejar CA crear los descriptores de acceso, anular +needsDisplayForKey:
e implementar -drawInContext:
para pasar el valor actual de la propiedad sceneCenterPoint
al procesador y pedir que acabe con la escena:
#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];
}
...
(Si usted tiene acceso a los vídeos de las sesiones de la WWDC 2009, puede revisar esta técnica en la sesión 303 ("dibujo animado")).
Ahora, cuando se crea una animación explícita para la capa en la keyPath @"sceneCenterPoint"
, Core Animation debe calcular los valores interpolados de las propiedades personalizadas y llame -drawInContext:
para cada paso de la animación:
- (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];
}
Al menos eso es lo que sucedería para una subclase CALayer
normal. Cuando subclase CAEAGLLayer
, consigo esta salida en la consola para cada paso de la animación:
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. ...
Así que parece que, posiblemente por razones de rendimiento, para las capas de OpenGL, -drawInContext:
no está recibiendo llamadas porque estas capas no usan el método estándar -display
para dibujarse. ¿Alguien puede confirmar eso? ¿Hay alguna forma de evitarlo?
¿O no puedo usar la técnica que expuse arriba? Esto significaría que tendría que implementar las animaciones manualmente en el renderizador OpenGL (que es posible pero no tan elegante como IMO).
Gracias por la sugerencia. Lo probaré e informaré. –
¡De hecho funciona de esa manera, muchas gracias! El rendimiento no parece ser tan bueno como una solución pura de OpenGL, pero pronto escribiré una publicación en el blog sobre los detalles. –