Изменить: я полагаю, что вместо длинного объяснения ниже я также могу спросить: Отправка -setNeedsDisplay
экземпляру CAEAGLLayer
не приводит к перерисовке слоя (т.е. -drawInContext:
не вызывается). Вместо этого я получаю это сообщение консоли:
<GLLayer: 0x4d500b0>: calling -display has no effect.
Есть ли способ решить эту проблему? Могу ли я вызвать -drawInContext:
, когда вызывается -setNeedsDisplay
? Длинное объяснение ниже:
У меня есть сцена OpenGL, которую я хотел бы оживить, используя анимацию Core Animation.
Следуя стандартным подходам к анимации пользовательских свойств в CALayer, я создал подкласс CAEAGLLayer
и определил свойство sceneCenterPoint
в нем, значение которого должно быть анимировано. Мой слой также содержит ссылку на рендеринг 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;
Затем я объявляю свойство @dynamic
, чтобы CA создавал accessors, переопределял +needsDisplayForKey:
и реализовал -drawInContext:
, чтобы передать текущее значение свойства sceneCenterPoint
в средство визуализации и попросить его визуализировать сцену:
#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];
}
...
(Если у вас есть доступ к видеороликам сеанса WWDC 2009, вы можете просмотреть этот метод в сеансе 303 ( "Анимированный чертеж" )).
Теперь, когда я создаю явную анимацию для слоя на keyPath @"sceneCenterPoint"
, Core Animation должна рассчитать интерполированные значения для пользовательских свойств и вызвать -drawInContext:
для каждого шага анимации:
- (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];
}
По крайней мере, это будет происходить для обычного подкласса CALayer
. Когда я подклассом CAEAGLLayer
, я получаю этот вывод на консоли для каждого шага анимации:
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. ...
Похоже, что, по соображениям производительности, для слоев OpenGL, -drawInContext:
не получает вызов, потому что эти слои не используют стандартный метод -display
для рисования. Кто-нибудь может это подтвердить? Есть ли способ обойти это?
Или я не могу использовать технику, изложенную выше? Это означало бы, что я должен был бы выполнить анимацию вручную в рендерере OpenGL (что возможно, но не как изящная ИМО).