move to package

This commit is contained in:
2026-01-03 18:57:56 +01:00
parent f38cfaf677
commit e463618ce4
77 changed files with 761 additions and 17 deletions

View File

@@ -0,0 +1,11 @@
# Changelog
All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [0.1.0] - 2026-01-03
### This is the first release of *\<MosisSDK\>*.
*Short description of this release*

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 044d7c092cb6545f9865bbea183b5f23
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1eeef09f6ae7945569d85300042624ec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,169 @@
>>>
**_Package Documentation Template_**
Use this template to create preliminary, high-level documentation meant to introduce users to the feature and the sample files included in this package. When writing your documentation, do the following:
1. Follow instructions in blockquotes.
2. Replace angle brackets with the appropriate text. For example, replace "&lt;package name&gt;" with the official name of the package.
3. Delete sections that do not apply to your package. For example, a package containing only sample files does not have a "Using &lt;package_name&gt;" section, so this section can be removed.
4. After documentation is completed, make sure you delete all instructions and examples in blockquotes including this preamble and its title:
```
>>>
Delete all of the text between pairs of blockquote markdown.
>>>
```
>>>
# About &lt;package name&gt;
>>>
Name the heading of the first topic after the **displayName** of the package as it appears in the package manifest.
This first topic includes a brief, high-level explanation of the package and, if applicable, provides links to Unity Manual topics.
There are two types of packages:
- Packages that include features that augment the Unity Editor or Runtime.
- Packages that include sample files.
Choose one of the following introductory paragraphs that best fits the package:
>>>
Use the &lt;package name&gt; package to &lt;list of the main uses for the package&gt;. For example, use &lt;package name&gt; to create/generate/extend/capture &lt;mention major use case, or a good example of what the package can be used for&gt;. The &lt;package name&gt; package also includes &lt;other relevant features or uses&gt;.
> *or*
The &lt;package name&gt; package includes examples of &lt;name of asset type, model, prefabs, and/or other GameObjects in the package&gt;. For more information, see &lt;xref to topic in the Unity Manual&gt;.
>>>
**_Examples:_**
Here are some examples for reference only. Do not include these in the final documentation file:
*Use the Unity Recorder package to capture and save in-game data. For example, use Unity Recorder to record an mp4 file during a game session. The Unity Recorder package also includes an interface for setting-up and triggering recording sessions.*
*The Timeline Examples package includes examples of Timeline assets, Timeline Instances, animation, GameObjects, and scripts that illustrate how to use Unity's Timeline. For more information, see [ Unity's Timeline](https://docs.unity3d.com/Manual/TimelineSection.html) in the [Unity Manual](https://docs.unity3d.com). For licensing and usage, see Package Licensing.*
>>>
# Installing &lt;package name&gt;
>>>
Begin this section with a cross-reference to the official Unity Manual topic on how to install packages. If the package requires special installation instructions, include these steps in this section.
>>>
To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html).
>>>
For some packages, there may be additional steps to complete the setup. You can add those here.
>>>
In addition, you need to install the following resources:
- &lt;name of resource&gt;: To install, open *Window > &lt;name of menu item&gt;*. The resource appears &lt;at this location&gt;.
- &lt;name of sample&gt;: To install, open *Window > &lt;name of menu item&gt;*. The new sample folder appears &lt;at this location&gt;.
<a name="UsingPackageName"></a>
# Using &lt;package name&gt;
>>>
The contents of this section depends on the type of package.
For packages that augment the Unity Editor with additional features, this section should include workflow and/or reference documentation:
* At a minimum, this section should include reference documentation that describes the windows, editors, and properties that the package adds to Unity. This reference documentation should include screen grabs (see how to add screens below), a list of settings, an explanation of what each setting does, and the default values of each setting.
* Ideally, this section should also include a workflow: a list of steps that the user can easily follow that demonstrates how to use the feature. This list of steps should include screen grabs (see how to add screens below) to better describe how to use the feature.
For packages that include sample files, this section may include detailed information on how the user can use these sample files in their projects and scenes. However, workflow diagrams or illustrations could be included if deemed appropriate.
## How to add images
*(This section is for reference. Do not include in the final documentation file)*
If the [Using &lt;package name&gt;](#UsingPackageName) section includes screen grabs or diagrams, a link to the image must be added to this MD file, before or after the paragraph with the instruction or description that references the image. In addition, a caption should be added to the image link that includes the name of the screen or diagram. All images must be PNG files with underscores for spaces. No animated GIFs.
An example is included below:
![A cinematic in the Timeline Editor window.](images/example.png)
Notice that the example screen shot is included in the images folder. All screen grabs and/or diagrams must be added and referenced from the images folder.
For more on the Unity documentation standards for creating and adding screen grabs, see this confluence page: https://confluence.hq.unity3d.com/pages/viewpage.action?pageId=13500715
>>>
# Technical details
## Requirements
>>>
This subtopic includes a bullet list with the compatible versions of Unity. This subtopic may also include additional requirements or recommendations for 3rd party software or hardware. An example includes a dependency on other packages. If you need to include references to non-Unity products, make sure you refer to these products correctly and that all references include the proper trademarks (tm or r)
>>>
This version of &lt;package name&gt; is compatible with the following versions of the Unity Editor:
* 2018.1 and later (recommended)
To use this package, you must have the following 3rd party products:
* &lt;product name and version with trademark or registered trademark.&gt;
* &lt;product name and version with trademark or registered trademark.&gt;
* &lt;product name and version with trademark or registered trademark.&gt;
## Known limitations
>>>
This section lists the known limitations with this version of the package. If there are no known limitations, or if the limitations are trivial, exclude this section. An example is provided.
>>>
&lt;package name&gt; version &lt;package version&gt; includes the following known limitations:
* &lt;brief one-line description of first limitation.&gt;
* &lt;brief one-line description of second limitation.&gt;
* &lt;and so on&gt;
>>>
*Example (For reference. Do not include in the final documentation file):*
The Unity Recorder version 1.0 has the following limitations:*
* The Unity Recorder does not support sound.
* The Recorder window and Recorder properties are not available in standalone players.
* MP4 encoding is only available on Windows.
>>>
## Package contents
>>>
This section includes the location of important files you want the user to know about. For example, if this is a sample package containing textures, models, and materials separated by sample group, you may want to provide the folder location of each group.
>>>
The following table indicates the &lt;describe the breakdown you used here&gt;:
|Location|Description|
|---|---|
|`<folder>`|Contains &lt;describe what the folder contains&gt;.|
|`<file>`|Contains &lt;describe what the file represents or implements&gt;.|
>>>
*Example (For reference. Do not include in the final documentation file):*
The following table indicates the root folder of each type of sample in this package. Each sample's root folder contains its own Materials, Models, or Textures folders:
|Folder Location|Description|
|---|---|
|`WoodenCrate_Orange`|Root folder containing the assets for the orange crates.|
|`WoodenCrate_Mahogany`|Root folder containing the assets for the mahogany crates.|
|`WoodenCrate_Shared`|Root folder containing any material assets shared by all crates.|
>>>
## Document revision history
>>>
This section includes the revision history of the document. The revision history tracks when a document is created, edited, and updated. If you create or update a document, you must add a new row describing the revision. The Documentation Team also uses this table to track when a document is edited and its editing level. An example is provided:
|Date|Reason|
|---|---|
|Sept 12, 2017|Unedited. Published to package.|
|Sept 10, 2017|Document updated for package version 1.1.<br>New features: <li>audio support for capturing MP4s.<li>Instructions on saving Recorder prefabs|
|Sept 5, 2017|Limited edit by Documentation Team. Published to package.|
|Aug 25, 2017|Document created. Matches package version 1.0.|
>>>

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8a7abe04ea9404698a5e63ad0c665df0
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cb56324baf9714165a4b145418bf4ccd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: 5a49a892672c944f9aa7b97525891ab8
TextureImporter:
internalIDToNameTable:
- first:
213: -8196121713257968172
second: example_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: example_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 748
height: 249
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 4dd84690ab6814e80800000000000000
internalID: -8196121713257968172
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
example_0: -8196121713257968172
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e8fda4daa34f14b749be2fa439fcf720
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,93 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Android;
using System.IO;
using UnityEngine;
using System;
using System.Xml;
public class AndroidPostProcess : IPostGenerateGradleAndroidProject
{
public int callbackOrder => 0;
public void OnPostGenerateGradleAndroidProject(string buildPath)
{
// 1. Get the path to the Unity-generated CMakeLists.txt in the build folder
// path parameter is: PROJECT_ROOT/Library/Bee/Android/Prj/Mono2x/Gradle/unityLibrary
string targetCmakeFile = Path.Combine(buildPath, "src/main/cpp/CMakeLists.txt");
if (!File.Exists(targetCmakeFile)) return;
// 2. Locate your custom C++ folder in Assets
// Application.dataPath gives the absolute path to "Assets"
string myCppFolder = Path.GetFullPath(Path.Combine(Application.dataPath, "../Packages/com.omarator.mosissdk/Plugins/Android/cpp"));
// 3. Calculate the relative path from the build's CMake location to your source
// We need the directory where the target CMake file lives to calculate relative from it
string targetCmakeDir = Path.GetDirectoryName(targetCmakeFile);
string relativePathToMyCpp = GetRelativePath(targetCmakeDir, myCppFolder).Replace("\\", "/");
// 4. Prepare the command
string commandName = "my_plugin_build";
string lineToAdd = $"\nadd_subdirectory(\"{relativePathToMyCpp}\" \"{commandName}\")\n";
// 5. Prevent multiple additions
string currentContent = File.ReadAllText(targetCmakeFile);
if (!currentContent.Contains(relativePathToMyCpp))
{
File.AppendAllText(targetCmakeFile, lineToAdd);
Debug.Log($"[CMake] Added {relativePathToMyCpp} to build.");
}
ModifyManifest(buildPath);
}
// Helper for cross-platform relative paths
private string GetRelativePath(string fromPath, string toPath)
{
Uri fromUri = new Uri(AppendSlash(fromPath));
Uri toUri = new Uri(AppendSlash(toPath));
Uri relativeUri = fromUri.MakeRelativeUri(toUri);
return Uri.UnescapeDataString(relativeUri.ToString());
}
private string AppendSlash(string path)
{
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString()))
path += Path.DirectorySeparatorChar;
return path;
}
public void ModifyManifest(string path)
{
// The manifest is located in the unityLibrary module
string manifestPath = Path.Combine(path, "src/main/AndroidManifest.xml");
XmlDocument doc = new XmlDocument();
doc.Load(manifestPath);
XmlNode root = doc.DocumentElement;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("android", "http://schemas.android.com/apk/res/android");
// 1. Check/Add Queries tag
XmlNode queriesNode = root.SelectSingleNode("queries");
if (queriesNode == null)
{
queriesNode = doc.CreateElement("queries");
root.AppendChild(queriesNode);
}
// 2. Add the specific package if it's not there
string targetPackage = "com.omixlab.mosis";
if (queriesNode.SelectSingleNode($"package[@android:name='{targetPackage}']", nsmgr) == null)
{
XmlElement packageElem = doc.CreateElement("package");
packageElem.SetAttribute("name", "http://schemas.android.com/apk/res/android", targetPackage);
queriesNode.AppendChild(packageElem);
}
doc.Save(manifestPath);
Debug.Log("[Manifest] Successfully injected <queries> tag.");
}
}
#endif

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 813722810ec374244ad7f0fbd8b40b7e

View File

@@ -0,0 +1,30 @@
// -----------------------------------------------------------------------------
//
// Use this editor example C# file to develop editor (non-runtime) code.
//
// -----------------------------------------------------------------------------
namespace Omarator.Mosissdk.Editor
{
/// <summary>
/// Provide a general description of the public class.
/// </summary>
/// <remarks>
/// Packages require XmlDoc documentation for ALL Package APIs.
/// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/xml-documentation-comments
/// </remarks>
public class MyPublicEditorExampleClass
{
/// <summary>
/// Provide a description of what this private method does.
/// </summary>
/// <param name="parameter1"> Description of parameter 1 </param>
/// <param name="parameter2"> Description of parameter 2 </param>
/// <param name="parameter3"> Description of parameter 3 </param>
/// <returns> Description of what the function returns </returns>
public int CountThingsAndDoStuff(int parameter1, int parameter2, bool parameter3)
{
return parameter3 ? (parameter1 + parameter2) : (parameter1 - parameter2);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 98e9eff0dd13f4379b8069286df2eb7f

View File

@@ -0,0 +1,10 @@
{
"name": "Omarator.Mosissdk.Editor",
"references": [
"Omarator.Mosissdk"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0137830c41d4a4cfea332d24c6f9074f
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e283b895662f045d89d8d8be39dbf68b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1cbd7617bffb546ec80e5c75c643ddc0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
package com.omixlab.mosis.unity
import android.util.Log
import android.content.ComponentName
import android.content.Context.BIND_AUTO_CREATE
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import androidx.core.content.ContextCompat.startForegroundService
import com.omixlab.mosis.IMosisService
import com.unity3d.player.UnityPlayer
class MyKotlinPlugin {
companion object {
val instance: MyKotlinPlugin by lazy { MyKotlinPlugin() }
@JvmStatic
fun StartMosisService() {
instance.startRemoteService()
}
}
var remote_service: IMosisService? = null
val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
Log.d("MosisTest", "Service Connected")
remote_service = IMosisService.Stub.asInterface(service)
Log.d("MosisTest", "Number: ${remote_service?.number}")
serviceConnected(service)
}
override fun onServiceDisconnected(arg0: ComponentName) {
Log.d("MosisTest", "Service Disconnected")
}
}
fun startRemoteService() {
val intent = Intent("com.omixlab.mosis.SERVICE")
intent.setPackage("com.omixlab.mosis")
val currentActivity = UnityPlayer.currentActivity
try {
startForegroundService(currentActivity, intent)
val result = currentActivity.bindService(intent, connection, BIND_AUTO_CREATE)
Log.d("MosisTest", "Bind result: $result")
} catch (e: Exception) {
Log.e("MosisTest", "Bind failed", e)
}
}
external fun serviceConnected(binder: IBinder)
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2a4d588f6f5f5424ca8c5e3885c951ba

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0366819e591a440a48281f7386275d17
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1166ea2c496784b4bba8295123b248a7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a615486c1ed22429a9db60a4b567faa2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
package android.hardware;
@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable HardwareBuffer ndk_header "android/hardware_buffer_aidl.h";

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 75d8b5cdaa87e4797a7e59862e4d7e89
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b44d8db48a75e488d89f7d7f5839ecb5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ae40e14fe44eb471aba26128ec535b27
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1608a3841bd2a4f2793ace76c2a4582a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
package com.omixlab.mosis;
import android.hardware.HardwareBuffer;
// oneway = fire-and-forget (asynchronous)
oneway interface IMosisListener {
void onServiceInitialized(boolean success);
void onBufferAvailable(in HardwareBuffer buffer);
void onFrameAvailable();
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 08472853f0bb04dfb8fb91a8c87d5af5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
package com.omixlab.mosis;
import com.omixlab.mosis.IMosisListener;
interface IMosisService {
boolean initOS(IMosisListener listener);
int getNumber();
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8b212b10f095b40698e0f88dd1642b9c
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2e9dff155f6b041d28dc2143160a5684
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.22.1)
project("MyNativePlugin")
find_library(log-lib log)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PLUGIN_API "/Applications/Unity/Hub/Editor/6000.3.2f1/Unity.app/Contents/PluginAPI")
set(ANDROID_SDK "/Users/omar/Library/Android/sdk")
set(BINDER_DIR "${ANDROID_SDK}/platforms/android-36/optional/libbinder_ndk_cpp")
set(SHARED_SRC_DIR "/Users/omar/Desktop/NativeService/src/main/cpp/")
add_library(my_native_lib SHARED
my_native_code.cpp
${SHARED_SRC_DIR}/com/omixlab/mosis/IMosisService.cpp
${SHARED_SRC_DIR}/com/omixlab/mosis/IMosisListener.cpp
${SHARED_SRC_DIR}/logger.cpp
${SHARED_SRC_DIR}/external_texture.cpp
${SHARED_SRC_DIR}/render_target.cpp
${SHARED_SRC_DIR}/glad/src/egl.c
${SHARED_SRC_DIR}/glad/src/gles2.c
)
target_link_libraries(my_native_lib ${log-lib} binder_ndk EGL GLESv2 nativewindow)
target_include_directories(my_native_lib PUBLIC
${SHARED_SRC_DIR}
${SHARED_SRC_DIR}/glad/include
${BINDER_DIR}
${PLUGIN_API}
)

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 321e7452e1c8c4c74812b77bd3f296d5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 604c411489f9043dcbd071e443f5dc07
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,195 @@
#include <jni.h>
#include <aidl/com/omixlab/mosis/IMosisListener.h>
#include <aidl/com/omixlab/mosis/BnMosisListener.h>
#include <logger.h>
#include <aidl/com/omixlab/mosis/IMosisService.h>
#include <android/binder_ibinder_jni.h>
#include <format>
#include <glad/gles2.h>
#include <glad/egl.h>
#include <IUnityGraphics.h>
#include <external_texture.h>
#include <render_target.h>
using namespace aidl::com::omixlab::mosis;
using namespace aidl::android::hardware;
std::shared_ptr<class IMosisService> g_service;
std::shared_ptr<class ServiceContext> g_context;
class TextureBlitter
{
GLuint source_texture = 0;
GLuint source_fb = 0;
GLuint dest_texture = 0;
GLuint dest_fb = 0;
GLint width;
GLint height;
public:
bool create(AHardwareBuffer* hardwareBuffer)
{
AHardwareBuffer_Desc desc{};
AHardwareBuffer_describe(hardwareBuffer, &desc);
width = desc.width;
height = desc.height;
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
EGLImageKHR eglImage = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, clientBuffer, nullptr);
if (eglImage == EGL_NO_IMAGE_KHR)
{
Logger::Log("Failed to create EGL image");
return false;
}
glGenTextures(1, &source_texture);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, source_texture);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);
eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
glGenFramebuffers(1, &source_fb);
glBindFramebuffer(GL_FRAMEBUFFER, source_fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_EXTERNAL_OES, source_texture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
glGenTextures(1, &dest_texture);
glBindTexture(GL_TEXTURE_2D, dest_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, desc.width, desc.height,
0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glGenFramebuffers(1, &dest_fb);
glBindFramebuffer(GL_FRAMEBUFFER, dest_fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, dest_texture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
blit();
return true;
}
[[nodiscard]] GLuint dest_texture_id() const
{
return dest_texture;
}
void blit()
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, source_fb);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dest_fb);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
};
typedef void (*OnMessageCallback)(const char*);
typedef void (*OnServiceInitializedCallback)(bool success);
typedef void (*OnFrameAvailableCallback)();
typedef void (*OnBufferReadyCallback)();
typedef void (*OnTextureReadyCallback)(GLuint gl_texture);
struct NativeCallbacks
{
OnMessageCallback OnMessage;
OnServiceInitializedCallback OnServiceInitialized;
OnFrameAvailableCallback OnFrameAvailable;
OnBufferReadyCallback OnBufferReady;
OnTextureReadyCallback OnTextureReady;
};
NativeCallbacks g_callbacks{};
class ServiceContext : public BnMosisListener
{
AHardwareBuffer* m_hwbuffer = nullptr;
std::unique_ptr<TextureBlitter> m_texture;
public:
ndk::ScopedAStatus onServiceInitialized(bool in_success) override
{
Logger::Log("onServiceInitialized");
g_callbacks.OnMessage("onServiceInitialized");
g_callbacks.OnServiceInitialized(in_success);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onFrameAvailable() override
{
Logger::Log("onFrameAvailable");
g_callbacks.OnMessage("onFrameAvailable");
g_callbacks.OnFrameAvailable();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onBufferAvailable(const HardwareBuffer &in_buffer) override
{
Logger::Log("onBufferAvailable");
g_callbacks.OnMessage("onBufferAvailable");
m_hwbuffer = in_buffer.get();
AHardwareBuffer_acquire(m_hwbuffer);
g_callbacks.OnBufferReady();
return ndk::ScopedAStatus::ok();
}
[[nodiscard]] GLuint create_texture()
{
m_texture = std::make_unique<TextureBlitter>();
m_texture->create(m_hwbuffer);
return m_texture->dest_texture_id();
}
void update_texture()
{
if (m_texture)
m_texture->blit();
}
};
extern "C" void SetNativeCallbacks(const NativeCallbacks& ptr)
{
g_callbacks = ptr;
}
extern "C" UnityRenderingEvent InitGLAD()
{
return [](int eventId){
gladLoaderLoadEGL(EGL_NO_DISPLAY);
int egl_version = gladLoadEGL(eglGetCurrentDisplay(), eglGetProcAddress);
if (egl_version == 0)
{
Logger::Log("Failed to load EGL");
return;
}
int gl_version = gladLoaderLoadGLES2();
if (gl_version == 0)
{
Logger::Log("Failed to load GL");
return;
}
if (g_context)
{
GLuint texture = g_context->create_texture();
g_callbacks.OnTextureReady(texture);
}
};
}
extern "C" UnityRenderingEvent UpdateTexture()
{
return [](int eventId){
if (g_context)
{
g_context->update_texture();
}
};
}
extern "C"
JNIEXPORT void JNICALL
Java_com_omixlab_mosis_unity_MyKotlinPlugin_serviceConnected(JNIEnv *env, jobject thiz,
jobject binder)
{
AIBinder* pBinder = AIBinder_fromJavaBinder(env, binder);
const ndk::SpAIBinder spBinder(pBinder);
g_service = IMosisService::fromBinder(spBinder);
Logger::Log("Service Connected");
g_context = ndk::SharedRefBase::make<ServiceContext>();
bool result{};
g_service->initOS(g_context, &result);
Logger::Log(std::format("InitOS returned {}", result));
}

View File

@@ -0,0 +1,54 @@
fileFormatVersion: 2
guid: 2d802269589194242b4f22af14a9bc73
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Android:
enabled: 0
settings:
AndroidLibraryDependee: UnityLibrary
AndroidSharedLibraryType: Executable
CPU: ARMv7
Any:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
Editor:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux64:
enabled: 0
settings:
CPU: x86_64
OSXUniversal:
enabled: 0
settings:
CPU: None
Win:
enabled: 0
settings:
CPU: x86
Win64:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1 @@
Use this file to describe your package's features.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e7b9d07480e074bf093eabefcf188dd0
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7e8546bbab50f4b5294ff2aa36c6d5e9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
using UnityEngine;
using UnityEngine.Rendering;
using System;
using System.Runtime.InteropServices;
public class KotlinBridge : MonoBehaviour
{
static KotlinBridge Instance;
Texture2D texture;
[StructLayout(LayoutKind.Sequential)]
struct NativeCallbacks
{
public IntPtr OnMessage;
public IntPtr OnServiceInitialized;
public IntPtr OnFrameAvailable;
public IntPtr OnBufferReady;
public IntPtr OnTextureReady;
}
public delegate void OnMessageDelegate(string message);
public delegate void OnServiceInitializedDelegate(bool success);
public delegate void OnFrameAvailableDelegate();
public delegate void OnBufferReadyDelegate();
public delegate void OnTextureReadyDelegate(uint gl_texture);
[DllImport("my_native_lib")]
private static extern void SetNativeCallbacks(ref NativeCallbacks callbacks);
[DllImport("my_native_lib")]
private static extern IntPtr InitGLAD();
[DllImport("my_native_lib")]
private static extern IntPtr UpdateTexture();
[AOT.MonoPInvokeCallback(typeof(OnMessageDelegate))]
static void OnMessage(string message)
{
//Debug.Log("High-speed callback: " + message);
}
[AOT.MonoPInvokeCallback(typeof(OnServiceInitializedDelegate))]
static void OnServiceInitialized(bool success)
{
Debug.Log("Service Initialized: " + success);
}
[AOT.MonoPInvokeCallback(typeof(OnServiceInitializedDelegate))]
static void OnFrameAvailable()
{
UnityMainThreadDispatcher.Enqueue(() => {
GL.IssuePluginEvent(UpdateTexture(), 1);
});
}
[AOT.MonoPInvokeCallback(typeof(OnBufferReadyDelegate))]
static void OnBufferReady()
{
Debug.Log("Buffer Ready");
UnityMainThreadDispatcher.Enqueue(() => {
GL.IssuePluginEvent(InitGLAD(), 1);
});
}
[AOT.MonoPInvokeCallback(typeof(OnTextureReadyDelegate))]
static void OnTextureReady(uint gl_texture)
{
Debug.Log("Texture Ready: " + gl_texture);
UnityMainThreadDispatcher.Enqueue(() => {
var renderer = Instance.GetComponent<Renderer>();
//renderer.material = new Material(Instance.oesShader);
renderer.materials[2].mainTexture = Texture2D.CreateExternalTexture(1024, 1024,
TextureFormat.RGBA32, false, false, (IntPtr)gl_texture);
});
}
void Start()
{
Instance = this;
NativeCallbacks callbacks = new NativeCallbacks();
callbacks.OnMessage = Marshal.GetFunctionPointerForDelegate(new OnMessageDelegate(OnMessage));
callbacks.OnServiceInitialized = Marshal.GetFunctionPointerForDelegate(new OnServiceInitializedDelegate(OnServiceInitialized));
callbacks.OnFrameAvailable = Marshal.GetFunctionPointerForDelegate(new OnFrameAvailableDelegate(OnFrameAvailable));
callbacks.OnBufferReady = Marshal.GetFunctionPointerForDelegate(new OnBufferReadyDelegate(OnBufferReady));
callbacks.OnTextureReady = Marshal.GetFunctionPointerForDelegate(new OnTextureReadyDelegate(OnTextureReady));
SetNativeCallbacks(ref callbacks);
if (Application.platform == RuntimePlatform.Android)
{
using (var ktClass = new AndroidJavaClass("com.omixlab.mosis.unity.MyKotlinPlugin"))
{
ktClass.CallStatic("StartMosisService");
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 30d423b9d44d240e7a5d6bf14c711e45

View File

@@ -0,0 +1,6 @@
{
"name": "Omarator.Mosissdk",
"references": [],
"includePlatforms": [],
"excludePlatforms": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0a8ada65d54024e918e57ccad4157d28
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
// -----------------------------------------------------------------------------
//
// Use this runtime example C# file to develop runtime code.
//
// -----------------------------------------------------------------------------
namespace Omarator.Mosissdk
{
/// <summary>
/// Provide a general description of the public class.
/// </summary>
/// <remarks>
/// Packages require XmlDoc documentation for ALL Package APIs.
/// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/xml-documentation-comments
/// </remarks>
public class MyPublicRuntimeExampleClass
{
/// <summary>
/// Provide a description of what this private method does.
/// </summary>
/// <param name="parameter1"> Description of parameter 1 </param>
/// <param name="parameter2"> Description of parameter 2 </param>
/// <param name="parameter3"> Description of parameter 3 </param>
/// <returns> Description of what the function returns </returns>
public int CountThingsAndDoStuff(int parameter1, int parameter2, bool parameter3)
{
return parameter3 ? (parameter1 + parameter2) : (parameter1 - parameter2);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 362d6f07ea083437fa4a53500d86b64a

View File

@@ -0,0 +1,21 @@
using UnityEngine;
using System.Collections.Concurrent;
using System;
public class UnityMainThreadDispatcher : MonoBehaviour
{
private static readonly ConcurrentQueue<Action> ExecutionQueue = new ConcurrentQueue<Action>();
public static void Enqueue(Action action)
{
ExecutionQueue.Enqueue(action);
}
void Update()
{
while (ExecutionQueue.TryDequeue(out var action))
{
action.Invoke();
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b7bfde52f3a724ee3b494287fcd0aa8e

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 183281196c8dc41ebb6291d04d2ba66a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 95b9a7e8d5bf84920b646786f8e7f482
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,4 @@
{
"displayName":"Example Sample",
"description": "Replace this string with your own description of the sample. Delete the Samples folder if not needed."
}

View File

@@ -0,0 +1,28 @@
// -----------------------------------------------------------------------------
//
// Use this sample example C# file to develop samples to guide usage of APIs
// in your package.
//
// -----------------------------------------------------------------------------
namespace Omarator.Mosissdk
{
/// <summary>
/// Provide a general description of the public class.
/// </summary>
/// <remarks>
/// Packages require XmlDoc documentation for ALL Package APIs.
/// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/xml-documentation-comments
/// </remarks>
public class MyPublicSampleExampleClass
{
/// <summary>
/// Provide a description of what this public method does.
/// </summary>
public void CountThingsAndDoStuffAndOutputIt()
{
var result = new MyPublicRuntimeExampleClass().CountThingsAndDoStuff(1, 2, false);
Debug.Log("Call CountThingsAndDoStuffAndOutputIt returns " + result);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 98542e95cab6e4e41ba7599be4e9b6a3

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8582ecb2e3c5f481e9d04a73ddd63fc3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 112fd34582f7c4f3f850f07a6e62c6d1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using UnityEngine;
using UnityEditor;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
namespace Omarator.Mosissdk.Editor.Tests
{
class EditorExampleTest
{
[Test]
public void EditorSampleTestSimplePasses()
{
// Use the Assert class to test conditions.
}
// A UnityTest behaves like a coroutine in PlayMode
// and allows you to yield null to skip a frame in EditMode
[UnityTest]
public IEnumerator EditorSampleTestWithEnumeratorPasses()
{
// Use the Assert class to test conditions.
// yield to skip a frame
yield return null;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 546a0dc4da32647fb800e2ff4ddf41ef

View File

@@ -0,0 +1,14 @@
{
"name": "Omarator.Mosissdk.Editor.Tests",
"references": [
"Omarator.Mosissdk.Editor",
"Omarator.Mosissdk"
],
"optionalUnityReferences": [
"TestAssemblies"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1dc9eb0d4d74d4274a118c53ccef6f1e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6b8a881b27c2c47e1b41fcd439506016
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
{
"name": "Omarator.Mosissdk.Tests",
"references": [
"Omarator.Mosissdk"
],
"optionalUnityReferences": [
"TestAssemblies"
],
"includePlatforms": [],
"excludePlatforms": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7012233e3de3a49c58bb7a70bb8f04d8
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
namespace Omarator.Mosissdk.Tests
{
class RuntimeExampleTest
{
[Test]
public void PlayModeSampleTestSimplePasses()
{
// Use the Assert class to test conditions.
}
// A UnityTest behaves like a coroutine in PlayMode
// and allows you to yield null to skip a frame in EditMode
[UnityTest]
public IEnumerator PlayModeSampleTestWithEnumeratorPasses()
{
// Use the Assert class to test conditions.
// yield to skip a frame
yield return null;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d980d829f5e174dcaaa149cb4e879c37

View File

@@ -0,0 +1,16 @@
This package contains third-party software components governed by the license(s) indicated below:
---------
Component Name: [provide component name]
License Type: [Provide license type, i.e. "MIT", "Apache 2.0"]
[Provide License Details]
---------
Component Name: [provide component name]
License Type: [Provide license type, i.e. "MIT", "Apache 2.0"]
[Provide License Details]

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5ef06c57547cf415da395ff3f642af04
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
{
"name": "com.omixlab.mosis_sdk",
"displayName": "MosisSDK",
"version": "0.1.0",
"unity": "6000.3",
"unityRelease": "2f1",
"description": "Replace this with your own description of the package. \n\nFor best results, use this text to summarize: \n\u25aa What the package does \n\u25aa How it can benefit the user \n\nNote: Special formatting characters are supported, including line breaks ('\\n') and bullets ('\\u25AA').",
"dependencies": {
"com.unity.test-framework": "1.6.0"
},
"author": {
"name": "Omar Mohamed Ali",
"url": "http://www.example.com",
"email": "example@email.com"
},
"changelogUrl": "https://example.com/changelog.html",
"documentationUrl": "https://example.com/",
"licensesUrl": "https://example.com/licensing.html"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 46853107f54994b2991315d760cfb842
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,13 @@
{
"dependencies": {
"com.omixlab.mosis_sdk": {
"version": "file:com.omarator.mosissdk",
"depth": 0,
"source": "embedded",
"dependencies": {
"com.unity.test-framework": "1.6.0"
}
},
"com.unity.2d.animation": {
"version": "13.0.2",
"depth": 0,