|
1 | 1 | using AOT;
|
2 | 2 |
|
3 | 3 | using System;
|
| 4 | +using System.Collections; |
4 | 5 | using System.IO;
|
5 | 6 | using System.Runtime.InteropServices;
|
6 | 7 |
|
@@ -251,30 +252,68 @@ public static void Remove(int handle)
|
251 | 252 | }
|
252 | 253 | }
|
253 | 254 |
|
| 255 | + /// <summary> |
| 256 | + /// A reusable version of UnityEngine.WaitForSecondsRealtime to avoid |
| 257 | + /// GC allocs |
| 258 | + /// </summary> |
| 259 | + class ReusableWaitForSecondsRealtime : CustomYieldInstruction |
| 260 | + { |
| 261 | + private float waitTime; |
| 262 | + |
| 263 | + public float WaitTime |
| 264 | + { |
| 265 | + set |
| 266 | + { |
| 267 | + waitTime = Time.realtimeSinceStartup + value; |
| 268 | + } |
| 269 | + } |
| 270 | + |
| 271 | + public override bool keepWaiting |
| 272 | + { |
| 273 | + get |
| 274 | + { |
| 275 | + return Time.realtimeSinceStartup < waitTime; |
| 276 | + } |
| 277 | + } |
| 278 | + |
| 279 | + public ReusableWaitForSecondsRealtime(float time) |
| 280 | + { |
| 281 | + WaitTime = time; |
| 282 | + } |
| 283 | + } |
| 284 | + |
254 | 285 | // Name of the plugin when using [DllImport]
|
255 | | - const string PluginName = "NativeScript"; |
| 286 | + const string PLUGIN_NAME = "NativeScript"; |
256 | 287 |
|
257 | 288 | // Path to load the plugin from when running inside the editor
|
258 | 289 | #if UNITY_EDITOR_OSX
|
259 | | - const string PluginPath = "/Plugins/Editor/NativeScript.bundle/Contents/MacOS/NativeScript"; |
| 290 | + const string PLUGIN_PATH = "/Plugins/Editor/NativeScript.bundle/Contents/MacOS/NativeScript"; |
260 | 291 | #elif UNITY_EDITOR_LINUX
|
261 | | - const string PluginPath = "/Plugins/Editor/libNativeScript.so"; |
| 292 | + const string PLUGIN_PATH = "/Plugins/Editor/libNativeScript.so"; |
262 | 293 | #elif UNITY_EDITOR_WIN
|
263 | | - const string PluginPath = "/Plugins/Editor/NativeScript.dll"; |
| 294 | + const string PLUGIN_PATH = "/Plugins/Editor/NativeScript.dll"; |
264 | 295 | #endif
|
265 | | - |
| 296 | + |
| 297 | + enum InitMode : byte |
| 298 | + { |
| 299 | + FirstBoot, |
| 300 | + Reload |
| 301 | + } |
| 302 | + |
266 | 303 | #if UNITY_EDITOR
|
267 | 304 | // Handle to the C++ DLL
|
268 | 305 | static IntPtr libraryHandle;
|
269 | 306 |
|
270 | 307 | delegate void InitDelegate(
|
271 | | - int maxManagedObjects, |
| 308 | + IntPtr memory, |
| 309 | + int memorySize, |
| 310 | + InitMode initMode, |
272 | 311 | IntPtr releaseObject,
|
273 | 312 | IntPtr stringNew,
|
274 | 313 | IntPtr setException,
|
275 | 314 | IntPtr arrayGetLength,
|
276 | 315 | /*BEGIN INIT PARAMS*/
|
277 | | - IntPtr unityEngineVector3ConstructorSystemSingle_SystemSingle_SystemSingle, |
| 316 | + intmaxManagedObjects,IntPtr unityEngineVector3ConstructorSystemSingle_SystemSingle_SystemSingle, |
278 | 317 | IntPtr unityEngineVector3PropertyGetMagnitude,
|
279 | 318 | IntPtr unityEngineVector3MethodSetSystemSingle_SystemSingle_SystemSingle,
|
280 | 319 | IntPtr unityEngineVector3Methodop_AdditionUnityEngineVector3_UnityEngineVector3,
|
@@ -754,13 +793,15 @@ static T GetDelegate<T>(
|
754 | 793 | #else
|
755 | 794 | [DllImport(PluginName)]
|
756 | 795 | static extern void Init(
|
757 | | - int maxManagedObjects, |
| 796 | + IntPtr memory, |
| 797 | + int memorySize, |
| 798 | + initMode initMode, |
758 | 799 | IntPtr releaseObject,
|
759 | 800 | IntPtr stringNew,
|
760 | 801 | IntPtr setException,
|
761 | 802 | IntPtr arrayGetLength,
|
762 | 803 | /*BEGIN INIT PARAMS*/
|
763 | | - IntPtr unityEngineVector3ConstructorSystemSingle_SystemSingle_SystemSingle, |
| 804 | + intmaxManagedObjects,IntPtr unityEngineVector3ConstructorSystemSingle_SystemSingle_SystemSingle, |
764 | 805 | IntPtr unityEngineVector3PropertyGetMagnitude,
|
765 | 806 | IntPtr unityEngineVector3MethodSetSystemSingle_SystemSingle_SystemSingle,
|
766 | 807 | IntPtr unityEngineVector3Methodop_AdditionUnityEngineVector3_UnityEngineVector3,
|
@@ -1416,38 +1457,95 @@ IntPtr systemComponentModelDesignComponentRenameEventHandlerInvoke
|
1416 | 1457 | delegate void SystemComponentModelDesignComponentRenameEventHandlerRemoveDelegate(int thisHandle, int delHandle);
|
1417 | 1458 | /*END DELEGATE TYPES*/
|
1418 | 1459 |
|
| 1460 | + private static readonly string pluginPath = Application.dataPath + PLUGIN_PATH; |
1419 | 1461 | public static Exception UnhandledCppException;
|
1420 | 1462 | public static SetCsharpExceptionDelegate SetCsharpException;
|
| 1463 | + private static IntPtr memory; |
| 1464 | + private static int memorySize; |
1421 | 1465 |
|
1422 | 1466 | /// <summary>
|
1423 | 1467 | /// Open the C++ plugin and call its PluginMain()
|
1424 | 1468 | /// </summary>
|
1425 | 1469 | ///
|
1426 | | - /// <param name="maxManagedObjects"> |
1427 | | - /// Maximum number of simultaneous managed objects that the C++ plugin |
1428 | | - /// uses. |
| 1470 | + /// <param name="memorySize"> |
| 1471 | + /// Number of bytes of memory to make available to the C++ plugin |
1429 | 1472 | /// </param>
|
1430 | | - public static void Open( |
1431 | | - int maxManagedObjects) |
| 1473 | + public static void Open(int memorySize) |
1432 | 1474 | {
|
1433 | | - ObjectStore.Init(maxManagedObjects); |
1434 | | - /*BEGIN STRUCTSTORE INIT CALLS*/ |
1435 | | - NativeScript.Bindings.StructStore<UnityEngine.Resolution>.Init(maxManagedObjects); |
| 1475 | + /*BEGIN STORE INIT CALLS*/ |
| 1476 | + NativeScript.Bindings.ObjectStore.Init(1000); |
| 1477 | + NativeScript.Bindings.StructStore<UnityEngine.Resolution>.Init(1000); |
1436 | 1478 | NativeScript.Bindings.StructStore<UnityEngine.RaycastHit>.Init(1000);
|
1437 | | - NativeScript.Bindings.StructStore<UnityEngine.Playables.PlayableGraph>.Init(maxManagedObjects); |
1438 | | - NativeScript.Bindings.StructStore<UnityEngine.Animations.AnimationMixerPlayable>.Init(maxManagedObjects); |
1439 | | - NativeScript.Bindings.StructStore<System.Collections.Generic.KeyValuePair<string, double>>.Init(maxManagedObjects); |
1440 | | - NativeScript.Bindings.StructStore<UnityEngine.Ray>.Init(maxManagedObjects); |
1441 | | - NativeScript.Bindings.StructStore<UnityEngine.SceneManagement.Scene>.Init(maxManagedObjects); |
1442 | | - NativeScript.Bindings.StructStore<UnityEngine.Playables.PlayableHandle>.Init(maxManagedObjects); |
1443 | | - NativeScript.Bindings.StructStore<UnityEngine.XR.WSA.Input.InteractionSourcePose>.Init(maxManagedObjects); |
1444 | | - /*END STRUCTSTORE INIT CALLS*/ |
| 1479 | + NativeScript.Bindings.StructStore<UnityEngine.Playables.PlayableGraph>.Init(1000); |
| 1480 | + NativeScript.Bindings.StructStore<UnityEngine.Animations.AnimationMixerPlayable>.Init(1000); |
| 1481 | + NativeScript.Bindings.StructStore<System.Collections.Generic.KeyValuePair<string, double>>.Init(20); |
| 1482 | + NativeScript.Bindings.StructStore<UnityEngine.Ray>.Init(10); |
| 1483 | + NativeScript.Bindings.StructStore<UnityEngine.SceneManagement.Scene>.Init(1000); |
| 1484 | + NativeScript.Bindings.StructStore<UnityEngine.Playables.PlayableHandle>.Init(1000); |
| 1485 | + NativeScript.Bindings.StructStore<UnityEngine.XR.WSA.Input.InteractionSourcePose>.Init(1000); |
| 1486 | + /*END STORE INIT CALLS*/ |
1445 | 1487 |
|
| 1488 | + Bindings.memorySize = memorySize; |
| 1489 | + memory = Marshal.AllocHGlobal(memorySize); |
| 1490 | + OpenPlugin(InitMode.FirstBoot); |
| 1491 | + } |
| 1492 | + |
| 1493 | + // Reloading requires dynamic loading of the C++ plugin, which is only |
| 1494 | + // available in the editor |
| 1495 | +#if UNITY_EDITOR |
| 1496 | + /// <summary> |
| 1497 | + /// Reload the C++ plugin. Its memory is intact and false is passed for |
| 1498 | + /// the isFirstBoot parameter of PluginMain(). |
| 1499 | + /// </summary> |
| 1500 | + public static void Reload() |
| 1501 | + { |
| 1502 | + ClosePlugin(); |
| 1503 | + OpenPlugin(InitMode.Reload); |
| 1504 | + } |
| 1505 | + |
| 1506 | + /// <summary> |
| 1507 | + /// Poll the plugin for changes and reload if any are found. |
| 1508 | + /// </summary> |
| 1509 | + /// |
| 1510 | + /// <param name="pollTime"> |
| 1511 | + /// Number of seconds between polls. |
| 1512 | + /// </param> |
| 1513 | + /// |
| 1514 | + /// <returns> |
| 1515 | + /// Enumerator for this iterator function. Can be passed to |
| 1516 | + /// MonoBehaviour.StartCoroutine for easy usage. |
| 1517 | + /// </returns> |
| 1518 | + public static IEnumerator AutoReload(float pollTime) |
| 1519 | + { |
| 1520 | + // Get the original time |
| 1521 | + long lastWriteTime = File.GetLastWriteTime(pluginPath).Ticks; |
| 1522 | + |
| 1523 | + ReusableWaitForSecondsRealtime poll |
| 1524 | + = new ReusableWaitForSecondsRealtime(pollTime); |
| 1525 | + do |
| 1526 | + { |
| 1527 | + // Poll. Reload if the last write time changed. |
| 1528 | + long cur = File.GetLastWriteTime(pluginPath).Ticks; |
| 1529 | + if (cur != lastWriteTime) |
| 1530 | + { |
| 1531 | + Debug.Log("reloading at " + DateTime.Now); |
| 1532 | + lastWriteTime = cur; |
| 1533 | + Reload(); |
| 1534 | + } |
| 1535 | + |
| 1536 | + // Wait to poll again |
| 1537 | + poll.WaitTime = pollTime; |
| 1538 | + yield return poll; |
| 1539 | + } |
| 1540 | + while (true); |
| 1541 | + } |
| 1542 | +#endif |
| 1543 | + |
| 1544 | + private static void OpenPlugin(InitMode initMode) |
| 1545 | + { |
1446 | 1546 | #if UNITY_EDITOR
|
1447 | | - |
1448 | 1547 | // Open native library
|
1449 | | - libraryHandle = OpenLibrary( |
1450 | | - Application.dataPath + PluginPath); |
| 1548 | + libraryHandle = OpenLibrary(pluginPath); |
1451 | 1549 | InitDelegate Init = GetDelegate<InitDelegate>(
|
1452 | 1550 | libraryHandle,
|
1453 | 1551 | "Init");
|
@@ -1498,17 +1596,18 @@ public static void Open(
|
1498 | 1596 | SystemComponentModelDesignComponentRenameEventHandlerNativeInvoke = GetDelegate<SystemComponentModelDesignComponentRenameEventHandlerNativeInvokeDelegate>(libraryHandle, "SystemComponentModelDesignComponentRenameEventHandlerNativeInvoke");
|
1499 | 1597 | SetCsharpExceptionSystemNullReferenceException = GetDelegate<SetCsharpExceptionSystemNullReferenceExceptionDelegate>(libraryHandle, "SetCsharpExceptionSystemNullReferenceException");
|
1500 | 1598 | /*END MONOBEHAVIOUR GETDELEGATE CALLS*/
|
1501 | | - |
1502 | 1599 | #endif
|
1503 | | - |
1504 | 1600 | // Init C++ library
|
1505 | 1601 | Init(
|
1506 | | - maxManagedObjects, |
| 1602 | + memory, |
| 1603 | + memorySize, |
| 1604 | + initMode, |
1507 | 1605 | Marshal.GetFunctionPointerForDelegate(new ReleaseObjectDelegate(ReleaseObject)),
|
1508 | 1606 | Marshal.GetFunctionPointerForDelegate(new StringNewDelegate(StringNew)),
|
1509 | 1607 | Marshal.GetFunctionPointerForDelegate(new SetExceptionDelegate(SetException)),
|
1510 | 1608 | Marshal.GetFunctionPointerForDelegate(new ArrayGetLengthDelegate(ArrayGetLength)),
|
1511 | 1609 | /*BEGIN INIT CALL*/
|
| 1610 | + 1000, |
1512 | 1611 | Marshal.GetFunctionPointerForDelegate(new UnityEngineVector3ConstructorSystemSingle_SystemSingle_SystemSingleDelegate(UnityEngineVector3ConstructorSystemSingle_SystemSingle_SystemSingle)),
|
1513 | 1612 | Marshal.GetFunctionPointerForDelegate(new UnityEngineVector3PropertyGetMagnitudeDelegate(UnityEngineVector3PropertyGetMagnitude)),
|
1514 | 1613 | Marshal.GetFunctionPointerForDelegate(new UnityEngineVector3MethodSetSystemSingle_SystemSingle_SystemSingleDelegate(UnityEngineVector3MethodSetSystemSingle_SystemSingle_SystemSingle)),
|
@@ -1781,6 +1880,13 @@ public static void Open(
|
1781 | 1880 | /// </summary>
|
1782 | 1881 | public static void Close()
|
1783 | 1882 | {
|
| 1883 | + ClosePlugin(); |
| 1884 | + Marshal.FreeHGlobal(memory); |
| 1885 | + memory = IntPtr.Zero; |
| 1886 | + } |
| 1887 | + |
| 1888 | + private static void ClosePlugin() |
| 1889 | + { |
1784 | 1890 | #if UNITY_EDITOR
|
1785 | 1891 | CloseLibrary(libraryHandle);
|
1786 | 1892 | libraryHandle = IntPtr.Zero;
|
|
0 commit comments