How to call the c# script from objective-C code in Unity? - plugins

In Unity, Wen can call objective-C code from C# by import the function of objective-C as extern function.
But how call C# script code from objective-C ?

You can use
UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");
in which you fill your gameobject name which will receive this message and the message name.
You can implement your own delegate/event once you receive this message from native code. The limit of UnitySendMessage is when it arrives to Unity code, it is always 1 frame after you call this in native code. And it can only take string as parameter. But most of time it is not big problem.

The method to be used for this is UnitySendMessage. Have a look at Building Plugins for iOS or this blog which is partially written in Chinese.

Have a look at: http://www.tinytimgames.com/2010/01/10/the-unityobjective-c-divide/
The bolg post shows a technique that uses KVO (Key Value Observation) and the PlayerPrefs to pass commands from unity to objective-c.
PlayerPrefs.SetString("Commands",
String.Format("AwesomeCommand|{0}|{1}", awesome1, awesome2));

Turns out you can create a callback method that will allow you to do whatever you want.
Here is an example video showing it being done for OSX, but the C++ code is cross platform.
This guy has been doing videos on plugins for all the operating systems, but the mac one is the coolest so far, since it gives you function pointers to C# code.
http://www.youtube.com/watch?v=Q2dDK0ulDYY

Universal plugin for unity for iOS that allow mixing C# with objective-C
http://goo.gl/XDrQFh
Unity C#
var callbackClass = AKiOSMagic.CreateClass("MyCallbackClass", "NSObject");
callbackClass.AddMethod("methodWithArg:anotherArg:", (args)
{
// do something...
// args.GetObject(0);
// args.GetObject(1);
});
callbackClass.RegisterClass();
Objective-C
[[NSClassFromString(#"MyCallbackClass") new] methodWithArg:#"arg1" anotherArg:#"arg2"]

Related

Is there a Swift bridge for Python?

I developed a script to set attributes for my iTunes music library on my Mac using an Apple Script bridge called AppScript. AppScript Allowed me to write my code in native Python without having to learn Apple Script. AppSript would translate my native Python to Apple Script. Since Apple Script has been replaced with Swift I am wondering if there is a similar bridge for Swift. I have done my research, but no luck. Additionally if there is, can you provide an example of how to control iTunes(now Music) with said library? Thanks in advance
Swift is designed to use MacOS's programming APIs: AppKit, Quartz, CoreFoundation, NSObject, etc, rather than the higher level OSAX event-driven elements (open, print, close, document, window, etc) used in AppleScript.
The system-bundled python (2.7) comes with pyObjC, which allows python to use the same programming APIs that Swift does, e.g. "writing apps". PyObjC also contains a Scripting Bridge to the AppleScript events and objects. The canonical example code does use iTunes:
from Foundation import *
from ScriptingBridge import *
iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")
print iTunes.currentTrack().name()
(Obvs, this is python2 and you need to put brackets round the print command. Also, personally, I wouldn't import * everything, as it's very slow.)
Here are some other methods/attributes based on the Script Dictionary:
iTunes.nextTrack()
iTunes.previousTrack()
iTunes.playpause()
iTunes.fastForward()
iTunes.setShuffleEnabled_(False)
iTunes.currentPlaylist().playOnce_(False)
The system-bundled version of pyObjC is very old, but the library itself is still being developed. If you're using python3, then you should install the latest version of pyObjC.
FWIW, you can actually run uncompiled Swift as a 'script' in the shell.

How to get GLFW window Id of FlutterWindow

I am trying to build a video player using flutter for Desktop. There is a video_player plugin available for iOS and Android, but not for Desktop. So, for the time being thought of trying to use gstreamer for decoding and hardware rendering in C++ code as back-end to flutter. The idea is to pass the Window Id of the flutter window to gstreamer's glimagesink plugin for rendering the video.
I am using the latest code from https://github.com/google/flutter-desktop-embedding as the base for my experiments. Below mentioned points are with reference to this repo.
In file flutter-desktop-embedding/example/linux/main.cc, FlutterWindowController object is created as shown below.
flutter::FlutterWindowController flutter_controller(icu_data_path);
This internally calls
FlutterDesktopInit();
While hovering the mouse pointer on the above method, VS code shows the following
bool FlutterDesktopInit()
Sets up the library's graphic context. Must be called before any other
methods.
Note: Internally, this library uses GLFW, which does not support multiple
copies within the same process. Internally this calls glfwInit, which will
fail if you have called glfwInit elsewhere in the process.
It is clear that FlutterDesktopInit() uses GLFW to create window. Checked whether I can get the window handle. But, no luck. I could only get the FlutterWindow object as shown below.
flutter::FlutterWindow *win = flutter_controller.window();
Appreciate if somebody can give some hint on how to get the GLFW window handle, which can be used with glimagesink.
You can't get references to any GLFW objects through that API. This is by design because, as the comment you quoted says, you can't have multiple copies of GLFW within the same process. GLFW is statically linked into the Linux Flutter embedding, so you can't use GLFW in the runner or a plugin.
Implementing a video player should be done using the texture APIs, which will be added for GLFW in this PR.

Oculus VRC with Unity

I'm developping a game with Unity.
I'm trying to check all of the VRC (Virtual Reality Check) tests, especially TestResponseToRecenterRequest and TestAppShouldQuit ( link ).
My problem is, I have absolutly no idea how to listen these requests.
Most of forums said to use ovr_GetSessionStatus. However, it's a C++ method, not a C# one. Can you point me to a valid solution to listen ovr status or, at least, handle recenter and quit requests ?
Cordially
Probably you already fixed this, but i found that the ovr_GetSessionStatus is exposed as static variables on the OVRPlugin class, so you can check on an Update().
if (OVRPlugin.shouldRecenter)
{
OVRManager.display.RecenterPose();
}

Soundtouch bpm iPhone

I'm trying to integrate a mechanism to calculate the BPM of the song in the iPod library(also on iphone).
Searching on the web I found that the most used and reliable libraries to do this things is soundtouch.Anyone has experience with this library? It is computationally possible to make it run on the iPhone hardware?
I have recently been using the code from the BPMDetect class of the soundtouch library succesfully. Initially compiled it on C++, later on translated the code to C# and lately I've been using the C++ code on an Android app through JNI. I'm not really familiar with development in iOS but I'm almost certain that it is possible what you're trying to do.
The only files you should use from the soundtouch source code are the following:
C++ files
BPMDetect.cpp
FIFOSampleBuffer.cpp
PeakFinder.cpp
Header files
BPMDetect.h
FIFOSampleBuffer.h
FIFOSamplePipe.h
PeakFinder.h
soundtouch_config.h
STTypes.h
At least these are the only ones I had to use to make it work.
The BPMDetect class recieves raw samples through its inputSamples() method, it's capable of calculating a bpm value even when the whole file is not yet loaded into its buffer. I have found that these intermediate values differ from the one obtained once the whole file is loaded, which is more accurate, in my experience.
Hope this helps.
EDIT:
It's a kind of complex process to explain in a comment so I'm going to edit the answer.
The gist of it is that you need your android app to consume native code. In order to do that, you need to compile the files listed above from the soundtouch library with the Android NDK toolset.
That will leave you with native code that will be able to process raw sound data, but you still need to get the data from the sound file, which you can do several ways, I think. The way I was doing it was using the FMOD library for Android, here's a nice example for that: FMOD for Android.
Supposing you declared a method like this in your C code:
void Java_your_package_YourClassName_cPlay(JNIEnv *env, jobject thiz)
{
sound->play();
}
On the Android app you use your native methods in the following way:
public class Sound {
// Native method declaration
private native void cPlay();
public void play()
{
cPlay();
}
}
In order to have a friendlier API to work with you can create wrappers around these function calls.
I put the native C code I was using in a gist here.
Hope this helps.

EXC_BAD_ACCESS when sending messages to blocks on 4.0 -> 3.2

I've been using http://code.google.com/p/plblocks/ for a while now to get blocks support in our 3.2 iPad app. It was recently pointed out to me that you can set xcode to use the 4.0 SDK, then set the OS Deployment target to 3.2.
If I do, the following code works.
void (^world)() = ^ {
NSLog(#"Hello World");
};
NSLog(#"Hello?");
world();
However, any time I sent a message to a block I get an EXC_BAD_ACCESS. For example, if I add the following line:
void (^acopy)() = [world copy];
This is a problem, since you have to copy blocks in order for them to keep their scope around later. Any idea why blocks would work, but the messages wouldn't? Am I missing some setting or something? Am I mistaken about the need to copy?
It seems you can still use Block_copy(). I don't know why PLBlocks would be able to use the Objective-C and the built-in compilers can't.
Here's an intro article:
http://developer.apple.com/mac/articles/cocoa/introblocksgcd.html
It says:
Importantly, block objects are laid
out in such a way that they are also
Objective-C objects if that runtime is
present.
I can't really see how you could be developing an iPad app without the Objective-C runtime present. As a sanity check you could make sure the C version (Block_copy()) works.