2013-12-18 5 views
15

Кто-нибудь знает, как сделать «моментальный снимок» SKView или SKScene в NSImage?Render/Snapshot SpriteKit Сцена для NSImage

Мы смогли использовать API textureFromNode для создания SKTexture от узла и всех его дочерних элементов. Но пока мы не можем найти способ извлечь данные изображения, например, NSImage. Мы создаем смешанное приложение Cocoa/SpriteKit, в котором нам нужно извлечь мелкие миниатюры сцен.

Опять же, это кажется возможным на прошивке (чтобы получить UIImage) с помощью drawViewHierarchyInRect:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale); 
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; 
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

Но как сделать это на Cocoa с NSImage? Помогите.

+0

Это то, что вы ищете: http://stackoverflow.com/questions/3251261/how-do-i-take-a-screenshot-of-an-nsview – steffex

+0

Нет, ссылке, которую вы упоминание не работает для представлений на основе OpenGL (см. комментарии в нем), что имеет место для SKView. –

+0

Как насчет ответа по адресу: http://stackoverflow.com/questions/19571357/ios-sprite-kit-screengrab – Mark

ответ

0

Здесь была моя попытка (на OSX), чтобы выкопать, лежащий в основе вынесенное изображение ...

Во-первых, я подклассы SKView и в методе drawRect лениво схватил NSBitmapImageRep

if (![self cache]) 
    [self setCache:[self bitmapImageRepForCachingDisplayInRect:[self visibleRect]]]; 

я настроить a NSTimer, который периодически пытается скопировать содержимое этого кеша в пользовательский вид миниатюр:

MySKView *sv = ..... 
NSBitmapImageRep *cache = [sv cache]; 
if (!cache) 
    return; 

NSRect srcFrame = NSMakeRect(0,0,[sv frame].size.width,[sv frame].size.height); 
NSRect thumbFrame = [[self thumbView] frame]; 
NSRect thumbRect = NSMakeRect(0,0,thumbFrame.size.width,thumbFrame.size.height); 
[sv cacheDisplayInRect:srcFrame toBitmapImageRep:cache]; 
[[self thumbView] lockFocus]; 
[cache drawInRect:thumbRect 
     fromRect:srcFrame 
     operation:NSCompositeCopy 
     fraction:1.0 
    respectFlipped:YES 
      hints:nil]; 
[[self thumbView] unlockFocus]; 

Нет кубиков. Все, что я получаю в моем представлении thumbnail, является черным.

Вероятно по той же причине, что это все чертежи на основе OpenGL/GPU.

Это привело бы меня к тому, чтобы каким-то образом найти лежащий в основе контекст рисования OpenGL, используемый SKView, и сделать glReadPixels в этом контексте.

+0

В заголовках утверждается, что вы не можете подкласс SKView ... Я думаю, может быть, в обновлении: метод? – geowar

1

Нет прямого доступа к данным изображения из SKTexture. Вы можете представить узел в неэкранированной сцене и захватить иерархию представлений. Я использую этот код в прошивкой для справки:

class func imageFromNode(node : SKNode, inScene scene: SKScene) -> UIImage? { 
    if let texture = scene.view?.textureFromNode(node) { 
     let view = SKView(frame: CGRect(origin: CGPointZero, size: texture.size())) 
     view.allowsTransparency = true 
     view.backgroundColor = SKColor.clearColor() 

     let scene = SKScene(size: view.bounds.size) 
     scene.view?.allowsTransparency = true 
     scene.backgroundColor = SKColor.clearColor() 

     let sprite = SKSpriteNode(texture: texture) 
     sprite.position = CGPoint(x: CGRectGetMidX(view.frame), y: CGRectGetMidY(view.frame)) 
     scene.addChild(sprite) 
     view.presentScene(scene) 
     UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0) 
     view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true) 
     let image = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return image 
    } 
    return nil 
} 
0

SKView является UIView подклассом, так что вы должны быть в состоянии сделать слой мнения, в контексте CoreGraphics, а затем получить изображение из контекста.

Посмотрите на использование view.layer.drawInContext.

1

Начиная с OS X 10.11 (и iOS 9 и tvOS, но мы будем игнорировать их, так как вы спрашиваете о NSImage), SKTexture может экспортировать свое содержимое в CGImageRef. Так textureFromNode подход вы упоминаете сейчас первый шаг в рабочем растворе:

SKTexture *texture = [view textureFromNode: view.scene]; 
NSImage *image = [[NSImage alloc] initWithCGImage: texture.CGImage 
              size: view.bounds]; 

Примечание параметр size к initWithCGImage: вы можете пройти CGSizeZero там, чтобы сделать NSImage наследовать пиксельный размер CGImage, но так как вы можете иметь дело с дисплеем Retina, который, вероятно, вам нужен размер , который вы можете получить из размеров просмотра.