Receiving Xcode notification on Reality Composer animation end - swift

I have the following Reality Composer project that loads properly. As you can see, when the animation completes, it should notify with the keyword "attackComplete".
How do I get this notification?
import RealityKit
import ARKit
class ViewController: UIViewController, ARSessionDelegate {
#IBOutlet var arView: ARView!
override func viewDidLoad() {
super.viewDidLoad()
let boxAnchor = try! Experience.loadOrcAttack()
arView.session.delegate = self
arView.scene.anchors.append(boxAnchor)
print("done")
}
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
print(anchors)
}
}

With Reality Composer's notifications you can implement two scenarios:
Action listener
This is your case and it's easy to implement using
public var onAction: ((RealityKit.Entity?) -> Swift.Void)?.
import UIKit
import RealityKit
class ViewController: UIViewController {
#IBOutlet var arView: ARView!
let scene = try! Experience.loadScene()
override func viewDidLoad() {
super.viewDidLoad()
arView.scene.anchors.append(scene)
scene.actions.attackCompleted.onAction = notificationID // listener
}
fileprivate func notificationID(_ entity: Entity?) {
print(scene.actions.attackCompleted.identifier)
}
}
Here is one more example of how .onAction completion handler can be used.
Trigger for action
When you need to notify Reality Composer's scene to play an action use the following scenario:
import UIKit
import RealityKit
class ViewController: UIViewController {
#IBOutlet var arView: ARView!
let scene = try! Experience.loadScene()
override func viewDidLoad() {
super.viewDidLoad()
arView.scene.anchors.append(scene)
}
#IBAction func press(_ sender: UIButton) {
scene.notifications.spinner.post() // trigger for action
}
}
or use a subscript for [NAME.NotificationTrigger]:
#IBAction func press(_ sender: NSButton) {
scene.notifications.allNotifications[0].post()
}
Here's one more example of how .post() instance method can be used.
P. S.
If you need more info, read this post.

Related

Why am I unable to add anchor to arView scene after using removeAll()?

I'm trying to add and remove an anchor to my scene, but after removing it I'm unable to add it again. This might be because of the anchors added to the scene in the session function, but I'm not sure.
Do I need to run the session function again to add the anchorEntity to the scene again(not managed to do it due to some errors), or is there something else I'm missing...
Here is my code:
import UIKit
import RealityKit
import ARKit
class fvBoat: UIViewController, ARSessionDelegate {
#IBOutlet var arView: ARView!
let fvBoatAnchor = try! Vessel.loadFvBoatScene()
var imageAnchorToEntity: [ARImageAnchor: AnchorEntity] = [:]
override func viewDidLoad() {
super.viewDidLoad()
let fvBoat = fvBoatAnchor.fvBoatObject as? Entity & HasCollision
arView.installGestures(for: fvBoat!)
fvBoatAnchor.generateCollisionShapes(recursive: true)
// arView.scene.addAnchor(fvBoatAnchor)
arView.session.delegate = self
}
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
anchors.compactMap { $0 as? ARImageAnchor }.forEach {
let anchorEntity = AnchorEntity()
let modelEntity = fvBoatAnchor.fvBoatObject!
anchorEntity.addChild(modelEntity)
arView.scene.addAnchor(anchorEntity)
anchorEntity.transform.matrix = $0.transform
imageAnchorToEntity[$0] = anchorEntity
}
}
func installGestures(on object:ModelEntity){
object.generateCollisionShapes(recursive: true)
arView.installGestures(.all, for: object)
}
func leaveScene() {
arView?.session.pause()
arView?.session.delegate = nil
arView?.scene.anchors.removeAll()
arView?.removeFromSuperview()
arView?.window?.resignKey()
arView = nil
}
#IBAction func leaveScene(_ sender: Any) {
leaveScene()
}
#IBAction func addAnchor(_ sender: Any) {
arView.scene.addAnchor(fvBoatAnchor)
}
#IBAction func clearScene(_ sender: Any) {
arView.scene.anchors.removeAll()
}
}

SwiftUI UIViewRepresentable and Custom Delegate

When creating a UIViewControllerRepresentable for SwiftUI, how do you create a Coordinator so that it can access the delegate of a third party library?
In this case, I am trying to access BBMetal, a photo-filtering library.
This is a truncated version of the code we are trying to 'bridge' to SwiftUI:
class CameraPhotoFilterVC: UIViewController {
private var camera: BBMetalCamera!
private var metalView: BBMetalView!
private var faceView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
...
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
camera.start()
}...
}
extension CameraPhotoFilterVC: BBMetalCameraPhotoDelegate {
func camera(_ camera: BBMetalCamera, didOutput texture: MTLTexture) {
// do something with the photo
}
func camera(_ camera: BBMetalCamera, didFail error: Error) {
// In main thread
print("Fail taking photo. Error: \(error)")
}
}
Using UIViewRepresentable everything sets up properly and the CameraPhotoFilterVC works, starts up the camera, etc, but the extension does not respond. We tried to set this up as a Coordinator:
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<CameraPreviewView>) -> CameraViewController {
let cameraViewController = CameraViewController()
// Throws an error because what we really want is a BBMetalCameraPhotoDelegate
//cameraViewController.delegate = context.coordinator
return cameraViewController
}
class Coordinator: NSObject, BBMetalCameraPhotoDelegate {
var parent: CameraPreviewView
init(_ parent: CameraPreviewView) {
self.parent = parent
}
func camera(_ camera: BBMetalCamera, didOutput texture: MTLTexture) {
print("do something with the photo")
}
func camera(_ camera: BBMetalCamera, didFail error: Error) {
print("Fail taking photo. Error: \(error)")
}
}
We also tried simply leaving an extension of the ViewController:
final class CameraViewController : UIViewController {
...
}
extension CameraViewController: BBMetalCameraPhotoDelegate {
func camera(_ camera: BBMetalCamera, didOutput texture: MTLTexture) {
...
}
However the delegate methods from BBMetalCameraPhotoDelegate do not 'fire.
I suppose the question is: in UIViewControllerRepresentable or UIViewRepresentable, how do you add an "external" delegate in the makeUIViewController method?
Usually, if this was say a UIPickerView, the following line would work:
picker.delegate = context.coordinator
But in this case the delegate is 'once removed'
You need to set the BBMetalCamera's delegate at some point before you use it.
You might do it immediately after creating it. You didn't show how you create it, so I don't know if that would be a good place to set it.
You could probably just do it in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
camera.photoDelegate = self
}

Two windows are presented when I start my xib only project

I am using Xcode 10.1 two create a simple single window application. The issue is that I see two windows instantiated when I run it instead of the single one I expect. Here is my code
//AppDelegate
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var mainWindowController: WindowController!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
print("loading")
let mainWindowController = WindowController()
mainWindowController.showWindow(self)
self.mainWindowController = mainWindowController
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
print("closed")
}
}
//WindowController.swift
import Cocoa
class WindowController: NSWindowController, NSSpeechSynthesizerDelegate {
#IBOutlet weak var textField: NSTextField!
#IBOutlet weak var speakButton: NSButton!
#IBOutlet weak var stopButton: NSButton!
override var windowNibName: String {
return "Window"
}
let speechSynth = NSSpeechSynthesizer()
var isStarted: Bool = false {
didSet {
updateButtons()
}
}
override func windowDidLoad() {
super.windowDidLoad()
viewDidLoad()
}
func viewDidLoad() {
// super.viewDidLoad()
updateButtons()
speechSynth.delegate = self
print("view load")
// Do any additional setup after loading the view.
}
#IBAction func speakIt(sender: NSButton) {
let string = textField.stringValue
if string.isEmpty {
print("String is empty")
}
else {
print(string)
speechSynth.startSpeaking(string)
isStarted = true
}
}
#IBAction func stopIt(sender: NSButton) {
speechSynth.stopSpeaking()
isStarted = false
}
func updateButtons() {
if isStarted {
speakButton.isEnabled = false
stopButton.isEnabled = true
} else {
stopButton.isEnabled = false
speakButton.isEnabled = true
}
}
func speechSynthesizer(_ sender: NSSpeechSynthesizer, didFinishSpeaking finishedSpeaking: Bool) {
isStarted = false
}
}
My Xib has the option checked "Visible at launch". If I uncheck it, I see no window.
Basically, I am attempting a program from the book "Cocoa Programming for OSX". However, the book is obsolete. But I am trying to find my way through new Xcode and Swift. Any help?
Also a point worth noting is that only one window is functional, the second window IBOutlets and IBAction are not connected. So nothing happens in the second window.
I can't figure out why is this happening?

Take screenshot of ARKit view

How would I insert a button and use it to take a photo and place it in photo library. I have noticed when using arkit I cant drag buttons and place them over the view. I am seen some people online say you use snapshot() for taking the photo.
import UIKit
import SceneKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate {
#IBOutlet var sceneView: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// Show statistics such as fps and timing information
sceneView.showsStatistics = true
// Create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
// Set the scene to the view
sceneView.scene = scene
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
func session(_ session: ARSession, didFailWithError error: Error) {
// Present an error message to the user
}
func sessionWasInterrupted(_ session: ARSession) {
// Inform the user that the session has been interrupted, for example, by presenting an overlay
}
func sessionInterruptionEnded(_ session: ARSession) {
// Reset tracking and/or remove existing anchors if consistent tracking is required
}
}
I made a simple demo to show you how to combine snapshot(), ARSCNView and UIBUtton. So you may define your storyboard in this way:
as you can see, the button is inside the main view but outside and above the ARKit view
then your ViewController might be something like:
import UIKit
import ARKit
class ViewController: UIViewController {
#IBOutlet var arkitView:ARSCNView!
#IBOutlet var outputImageView:UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
arkitView.session.run(ARWorldTrackingConfiguration())
}
#IBAction func takeScreenshotAction() {
outputImageView.image = arkitView.snapshot()
}
}
final result is:

Sinch on swift 2

I am new in develop app for IOS and i am still learning but i can not handle a incoming call.
I do not know how to delegate and override the method. Can someone write a little example in swift 2.
Thats what i have until now, how can override the method didReceiveIncomingCall?
import Foundation
import UIKit
class LoginView: UIViewController, SINCallClientDelegate, SINCallDelegate{
#IBOutlet weak var labelUsuario: UILabel!
#IBOutlet weak var nameUsername: UILabel!
#IBAction func buttonDesconectar() {
//Add Disconnect code for VOIP
let defaults = NSUserDefaults.standardUserDefaults()
defaults.removeObjectForKey("usuario")
self.performSegueWithIdentifier("segueLoginViewToInicio", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
let vozIP = Sinch.clientWithApplicationKey(<APP_KEY>, applicationSecret: <APP_SECRET>, environmentHost: "sandbox.sinch.com", userId: "Roke" )
vozIP.setSupportCalling(true)
vozIP.setSupportActiveConnectionInBackground(true)
vozIP.start()
vozIP.startListeningOnActiveConnection()
}
}