Thanks to gchiste, I have achieved it by doing the following:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
private var label : SKLabelNode!
private var rectangle : SKShapeNode!
private var container : SKSpriteNode!
private var rectangle1 : SKShapeNode!
private var button : SKSpriteNode!
private var effectNode : SKEffectNode!
private var blurNode : SKShapeNode!
override func didMove(to view: SKView)
{
effectNode = SKEffectNode()
let blurFilter = CIFilter(name: "CIGaussianBlur", parameters: ["inputRadius": 20])
effectNode.filter = blurFilter
effectNode.zPosition = 500
addChild(effectNode)
blurNode = SKShapeNode(rect: self.frame)
blurNode.fillColor = .white
blurNode.isHidden = true
effectNode.addChild(blurNode)
self.container = SKSpriteNode()
//self.container.position = CGPoint(x: frame.width/2, y: frame.height/2)
self.container.size = CGSize(width: frame.width, height: frame.height)
self.container.color = UIColor(red: 0/255, green: 100/255, blue: 0/255, alpha: 1)
addChild(container)
self.label = SKLabelNode(text: "HELLO WORLD")
self.label.fontName = "Noteworthy-Bold"
self.label.fontSize = 100
self.label.alpha = 1.0
self.label.color = .red
self.label.zPosition = 2
self.label.position = self.convert(CGPoint(x: 5, y: 400),to: container)
self.container.addChild(self.label)
self.rectangle = SKShapeNode.init(rectOf: CGSize.init(width: 500, height: 500),
cornerRadius: 30)
self.rectangle.fillColor = UIColor.green
self.rectangle.strokeColor = .clear
self.rectangle.position = self.convert(self.rectangle.position, to: container)
self.container.addChild(self.rectangle)
self.button = SKSpriteNode(color: .blue, size: CGSize(width: 300, height: 100))
self.button.position = self.convert(CGPoint(x: 0, y: -400), to: container)
self.button.zPosition = 2
self.button.name = "button"
self.container.addChild(self.button)
}
override func touchesEnded(_ touches: Set, with event: UIEvent?)
{
let touch = touches.first
let positionInScene = touch!.location(in: self)
let allNodes = nodes(at: positionInScene)
for node in allNodes
{
let nodePositionConverted = self.convert(node.position, from: node)
let nodeFrameConverted = CGRect(origin: CGPoint(x:nodePositionConverted.x-node.frame.maxX,
y:nodePositionConverted.y-node.frame.maxY),
size:node.frame.size)
if nodeFrameConverted.contains(positionInScene)
{
if(node == button)
{
addMenu()
}
else if(node == rectangle1)
{
hideMenu()
}
}
}
}
func addMenu()
{
print("POINT A")
blurNode.isHidden = false
let fillTexture = self.view?.texture(from: container, crop: blurNode.frame)
print("POINT B")
blurNode.fillTexture = fillTexture
self.rectangle1 = SKShapeNode.init(rectOf: CGSize.init(width: 300, height: 300), cornerRadius: 30)
self.rectangle1.fillColor = UIColor.blue
self.rectangle1.zPosition = 600
addChild(rectangle1)
}
func hideMenu()
{
blurNode.isHidden = true
blurNode.fillTexture = nil
rectangle1.removeFromParent()
}
}
The only thing that bothers me is that it takes about a second or two before the blurred image appears. Does it take so long to create fillTexture from the container? Is there a way to do it more efficiently? Can it be done in the background thread?
Thanks!
EDIT 1: Seems like the delay is obvious in Simulator and not as much on an actual device...
EDIT 2: One more issue. The blurring effect does not cover the whole scene. The edges of the scene are not blurred. Any idea why? Thanks!