objective-c - game - spritekit tutorial
Render/Snapshot SpriteKit Scene a NSImage (4)
Aquí estaba mi intento (en OSX) de obtener la imagen renderizada subyacente ...
Primero, SKView
y en su método drawRect
agarré NSBitmapImageRep
un NSBitmapImageRep
if (![self cache])
[self setCache:[self bitmapImageRepForCachingDisplayInRect:[self visibleRect]]];
Luego configuré un NSTimer
que periódicamente intentaba copiar el contenido de ese caché a una vista en miniatura personalizada:
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];
No dados. Todo lo que obtengo en mi vista de ThumbNail es negro.
Probablemente por la misma razón que esto es todo el dibujo basado en OpenGL / GPU.
Eso me llevaría en la dirección de encontrar de alguna manera el contexto subyacente de dibujo OpenGL utilizado por SKView
y haciendo un glReadPixels
en ese contexto.
¿Alguien sabe cómo hacer una "instantánea" de un SKView
o SKScene
en un NSImage
?
Hemos podido usar la API textureFromNode
para crear una SKTexture
desde un nodo y todos sus elementos SKTexture
. Pero hasta ahora no podemos encontrar una manera de extraer los datos de la imagen en, por ejemplo, un NSImage
. Estamos construyendo una aplicación mixta Cocoa
/ SpriteKit
donde necesitamos extraer pequeñas miniaturas de escenas.
Nuevamente, esto parece posible en iOS (para obtener un UIImage
) usando drawViewHierarchyInRect
:
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
¿Pero cómo hacer esto en Cocoa
con NSImage
? Ayuda.
Todavía no hay acceso directo a los datos de imagen de una SKTexture. Puede presentar el nodo en una escena fuera de pantalla y capturar la jerarquía de vista. Uso este código en iOS como referencia:
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
}
SKView
es una subclase de UIView
, por lo que debería poder dibujar la capa de la vista en un contexto CoreGraphics y luego obtener la imagen del contexto.
Mira usando view.layer.drawInContext
.
A partir de OS X 10.11 (y iOS 9 y TVOS, pero los ignoraremos ya que está preguntando acerca de NSImage
), SKTexture
puede exportar su contenido a CGImageRef
. Entonces, el enfoque de textureFromNode
que mencionas ahora es el primer paso en una solución de trabajo:
SKTexture *texture = [view textureFromNode: view.scene];
NSImage *image = [[NSImage alloc] initWithCGImage: texture.CGImage
size: view.bounds];
Tenga en cuenta el parámetro de size
para initWithCGImage:
puede pasar CGSizeZero
allí para hacer que el NSImage
herede el tamaño de píxel de CGImage
, pero dado que puede tratar con Retina Display, probablemente desee el tamaño de punto , que puede obtener de las dimensiones de la vista.