Example #1
0
        /// <summary>
        /// Read from the queue into the consumer callable.
        ///
        /// <paramref name="consumer"/> is expected to return the number of bytes
        /// consumed, sans the header.
        /// </summary>
        /// <param name="consumer"></param>
        public int Read(Func <string, InteropMessageHeader, IntPtr, int> consumer)
        {
            return(messageConsumer.Read((ptr) =>
            {
                int bytesRead = 0;

                // Read target name (varying length string)
                int targetSize = FastStructure.PtrToStructure <int>(ptr + bytesRead);
                bytesRead += FastStructure.SizeOf <int>();

                string targetName = "";
                if (targetSize > 0)
                {
                    byte[] target = new byte[targetSize];

                    FastStructure.ReadBytes(target, ptr + bytesRead, 0, targetSize);
                    targetName = Encoding.UTF8.GetString(target);
                    bytesRead += targetSize;
                }

                // Read message header
                var headerSize = FastStructure.SizeOf <InteropMessageHeader>();
                var header = FastStructure.PtrToStructure <InteropMessageHeader>(ptr + bytesRead);
                bytesRead += headerSize;

                // Call consumer to handle the rest of the payload
                bytesRead += consumer(targetName, header, ptr + bytesRead);

                // InteropLogger.Debug($"Consume {bytesRead} bytes - {header.type} for `{targetName}`");

                return bytesRead;
            }, 0));
        }
Example #2
0
 internal static unsafe void PtrToStructure <T>(byte *ptr, out T structure)
     where T : struct
 {
     structure = FastStructure.PtrToStructure <T>((IntPtr)ptr);
     //var tr = __makeref(structure);
     //*(IntPtr*)&tr = (IntPtr)ptr;
     //structure = __refvalue( tr,T);
 }
Example #3
0
        private int OnConnect(string target, IntPtr ptr)
        {
            unityState         = FastStructure.PtrToStructure <InteropUnityState>(ptr);
            IsConnectedToUnity = true;

            InteropLogger.Debug($"{target} - {unityState.version} connected. Flavor Blasting.");

            SendAllSceneData();

            return(FastStructure.SizeOf <InteropUnityState>());
        }
Example #4
0
        public virtual void SimpleImageCaptureLoop()
        {
            using (var consumer = new CircularBuffer(name: "MySharedMemory", nodeCount: 4, nodeBufferSize: ((8294400 + FastStructure <MetaDataStruct> .Size)) * 2)) // Should be large enough to store 2 full hd raw image data + 4 Size of Struct
            {
                Stopwatch stopwatch = new Stopwatch();
                do
                {
                    stopwatch.Reset();
                    stopwatch.Start();
                    try
                    {
                        consumer.Read(intPtr =>
                        {
                            MetaDataStruct metaData = FastStructure.PtrToStructure <MetaDataStruct>(intPtr);
                            if (metaData.length > 0)
                            {
                                byte[] byteArray = new byte[metaData.length];
                                FastStructure.ReadArray <byte>(byteArray, intPtr, 0, byteArray.Length);

                                using (var bm = byteArray.ToBitmap(metaData.width, metaData.height, metaData.pitch, metaData.format))
                                {
                                    byte[] compressedJpgByteArray = bm.ToByteCompessedArray();
                                    Bitmap bitmap = compressedJpgByteArray.ToBitmap();

                                    pictureBox1.Invoke(new MethodInvoker(delegate()
                                    {
                                        if (pictureBox1.Image != null)
                                        {
                                            pictureBox1.Image.Dispose();
                                        }
                                        pictureBox1.Image = bitmap;
                                    }));
                                }
                            }
                            return(0);
                        }, timeout: MAX_SLEEP_TIME);
                    }
                    catch (TimeoutException exception)
                    {
                        Console.WriteLine(exception);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex);
                    }

                    int timeout = (int)(MAX_SLEEP_TIME - stopwatch.ElapsedMilliseconds);
                    Thread.Sleep(timeout >= 0 ? timeout : 0);
                } while (true);
            }
        }
Example #5
0
        public T this[int index]
        {
            get {
                if (index >= Length || index < 0)
                {
                    throw new IndexOutOfRangeException();
                }

                int offset = ElementSize * index;
                return(FastStructure.PtrToStructure <T>(
                           IntPtr.Add(ptr, offset)
                           ));
            }
        }
        public void CanAllocHGlobalReadWrite()
        {
            IntPtr mem = Marshal.AllocHGlobal(FastStructure.SizeOf <ComplexStructure>());

            ComplexStructure n = new ComplexStructure();

            n.Compatible.Integer1 = 1;
            n.Compatible.Bookend  = 2;

            n.FirstElement = 3;
            n.FinalElement = 9;
            unsafe
            {
                n.Compatible.Contents[0] = 4;
                n.Compatible.Contents[7] = 5;
            }

            FastStructure.StructureToPtr(ref n, mem);

            // Assert that the reading and writing result in same structure
            ComplexStructure m = FastStructure.PtrToStructure <ComplexStructure>(mem);

            Assert.Equal(n, m);
            Assert.Equal(n.Compatible.Integer1, m.Compatible.Integer1);
            Assert.Equal(n.Compatible.Bookend, m.Compatible.Bookend);
            unsafe
            {
                Assert.Equal(n.Compatible.Contents[0], m.Compatible.Contents[0]);
                Assert.Equal(n.Compatible.Contents[7], m.Compatible.Contents[7]);
            }

            // Assert that Marshal.PtrToStructure is compatible
            m = (ComplexStructure)Marshal.PtrToStructure(mem, typeof(ComplexStructure));
            Assert.Equal(n, m);
            Assert.Equal(n.Compatible.Integer1, m.Compatible.Integer1);
            Assert.Equal(n.Compatible.Bookend, m.Compatible.Bookend);
            unsafe
            {
                Assert.Equal(n.Compatible.Contents[0], m.Compatible.Contents[0]);
                Assert.Equal(n.Compatible.Contents[7], m.Compatible.Contents[7]);
            }

            Marshal.FreeHGlobal(mem);
        }
Example #7
0
        /// <summary>
        /// Read from the viewport image buffer and copy
        /// pixel data into the appropriate viewport.
        /// </summary>
        internal void ConsumePixels()
        {
            if (pixelsConsumer == null || pixelsConsumer.ShuttingDown)
            {
                return;
            }

            pixelsConsumer.Read((ptr) =>
            {
                var headerSize = FastStructure.SizeOf <InteropRenderHeader>();
                var header     = FastStructure.PtrToStructure <InteropRenderHeader>(ptr);

                if (!viewports.ContainsKey(header.viewportId))
                {
                    InteropLogger.Warning($"Got render texture for unknown viewport {header.viewportId}");
                    return(headerSize);
                }

                var viewport      = viewports[header.viewportId];
                var pixelDataSize = viewport.ReadPixelData(header, ptr + headerSize);

                return(headerSize + pixelDataSize);
            }, READ_WAIT);
        }
Example #8
0
        private int OnUpdateUnityState(string target, IntPtr ptr)
        {
            unityState = FastStructure.PtrToStructure <InteropUnityState>(ptr);

            return(FastStructure.SizeOf <InteropUnityState>());
        }
Example #9
0
        /// <summary>
        /// Consume a single message off the interop message queue
        /// </summary>
        /// <returns>Number of bytes read</returns>
        private int ConsumeMessage()
        {
            var disconnected = false;

            var bytesRead = messages.Read((target, header, ptr) =>
            {
                // While not connected - only accept connection requests
                if (!IsConnected)
                {
                    if (header.type != RpcRequest.Connect)
                    {
                        Debug.LogWarning($"Unhandled request type {header.type} for {target} - expected RpcRequest.Connect");
                    }

                    blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr);
                    OnConnectToBlender();
                    return(0);
                }

                switch (header.type)
                {
                case RpcRequest.UpdateBlenderState:
                    blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr);
                    break;

                case RpcRequest.Disconnect:
                    // Don't call OnDisconnectFromBlender() from within
                    // the read handler - we want to release the read node
                    // safely first before disposing the connection.
                    disconnected = true;
                    break;

                // Viewport messages
                case RpcRequest.AddViewport:
                    AddViewport(
                        target,
                        FastStructure.PtrToStructure <InteropViewport>(ptr)
                        );
                    break;

                case RpcRequest.RemoveViewport:
                    RemoveViewport(target);
                    break;

                case RpcRequest.UpdateViewport:
                    GetViewport(target).UpdateFromInterop(
                        FastStructure.PtrToStructure <InteropViewport>(ptr)
                        );
                    break;

                case RpcRequest.UpdateVisibleObjects:
                    var visibleObjectIds = new int[header.count];
                    FastStructure.ReadArray(visibleObjectIds, ptr, 0, header.count);
                    GetViewport(target).SetVisibleObjects(
                        visibleObjectIds
                        );
                    break;

                // Object messages
                case RpcRequest.AddObjectToScene:
                    AddObject(
                        target,
                        FastStructure.PtrToStructure <InteropSceneObject>(ptr)
                        );
                    break;

                case RpcRequest.RemoveObjectFromScene:
                    RemoveObject(target);
                    break;

                case RpcRequest.UpdateSceneObject:
                    UpdateObject(
                        target,
                        FastStructure.PtrToStructure <InteropSceneObject>(ptr)
                        );
                    break;

                // Mesh messages
                case RpcRequest.UpdateTriangles:
                    GetOrCreateMesh(target)
                    .triangles
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;

                case RpcRequest.UpdateVertices:
                    GetOrCreateMesh(target)
                    .vertices
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;

                case RpcRequest.UpdateNormals:
                    GetOrCreateMesh(target)
                    .normals
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;

                case RpcRequest.UpdateUV:
                    GetOrCreateMesh(target)
                    .uv
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;

                case RpcRequest.UpdateUV2:
                    GetOrCreateMesh(target)
                    .uv2
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;

                case RpcRequest.UpdateUV3:
                    GetOrCreateMesh(target)
                    .uv3
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;

                case RpcRequest.UpdateUV4:
                    GetOrCreateMesh(target)
                    .uv4
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;

                case RpcRequest.UpdateVertexColors:
                    GetOrCreateMesh(target)
                    .colors
                    .Resize(header.length)
                    .CopyFrom(ptr, header.index, header.count);
                    break;
                // TODO: ... and so on for weights/bones/etc

                case RpcRequest.UpdateMesh:
                    GetOrCreateMesh(target).UpdateFromInterop(
                        FastStructure.PtrToStructure <InteropMesh>(ptr)
                        );
                    break;

                // Texture messages
                case RpcRequest.UpdateTexture:
                    GetTexture(target).UpdateFromInterop(
                        FastStructure.PtrToStructure <InteropTexture>(ptr)
                        );
                    break;

                case RpcRequest.UpdateTextureData:
                    GetTexture(target).CopyFrom(
                        ptr, header.index, header.count, header.length
                        );
                    break;

                default:
                    Debug.LogWarning($"Unhandled request type {header.type} for {target}");
                    break;
                }

                // TODO: Necessary to count bytes? We won't read anything off this
                // buffer at this point so it's safe to drop the whole thing.
                // bytesRead will count the header size (indicating a message *was* read)
                return(0);
            });

            // Handle any disconnects that may have occured during the read
            if (disconnected)
            {
                OnDisconnectFromBlender();
            }

            return(bytesRead);
        }
Example #10
0
        /// <summary>
        /// Handle any messages coming from Blender
        /// </summary>
        private void ConsumeMessages()
        {
            Profiler.BeginSample("Consume Message");

            var disconnected = false;

            // TODO: Some messages should be skipped if !IsConnected.
            // Otherwise we may get a bad state. E.g. we see a disconnect
            // from Blender and THEN some other viewport/object data messages.

            messages.Read((target, header, ptr) =>
            {
                ObjectController obj;

                switch (header.type)
                {
                case RpcRequest.Connect:
                    blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr);
                    OnConnectToBlender();
                    break;

                case RpcRequest.UpdateBlenderState:
                    blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr);
                    break;

                case RpcRequest.Disconnect:
                    // Don't call OnDisconnectFromBlender() from within
                    // the read handler - we want to release the read node
                    // safely first before disposing the connection.
                    disconnected = true;
                    break;

                case RpcRequest.AddViewport:
                    AddViewport(
                        target,
                        FastStructure.PtrToStructure <InteropViewport>(ptr)
                        );
                    break;

                case RpcRequest.RemoveViewport:
                    RemoveViewport(target);
                    break;

                case RpcRequest.UpdateViewport:
                    GetViewport(target).UpdateFromInterop(
                        FastStructure.PtrToStructure <InteropViewport>(ptr)
                        );
                    break;

                case RpcRequest.UpdateVisibleObjects:
                    var visibleObjectIds = new int[header.count];
                    FastStructure.ReadArray(visibleObjectIds, ptr, 0, header.count);
                    GetViewport(target).SetVisibleObjects(
                        visibleObjectIds
                        );
                    break;

                case RpcRequest.AddObjectToScene:
                    AddObject(
                        target,
                        FastStructure.PtrToStructure <InteropSceneObject>(ptr)
                        );
                    break;

                case RpcRequest.RemoveObjectFromScene:
                    RemoveObject(target);
                    break;

                case RpcRequest.UpdateSceneObject:
                    GetObject(target).UpdateFromInterop(
                        FastStructure.PtrToStructure <InteropSceneObject>(ptr)
                        );
                    break;

                case RpcRequest.UpdateTriangles:
                    obj = GetObject(target);
                    FastStructure.ReadArray(obj.GetOrCreateTriangleBuffer(), ptr, header.index, header.count);
                    obj.OnUpdateTriangleRange(header.index, header.count);
                    break;

                case RpcRequest.UpdateVertices:
                    obj = GetObject(target);
                    FastStructure.ReadArray(obj.GetOrCreateVertexBuffer(), ptr, header.index, header.count);
                    obj.OnUpdateVertexRange(header.index, header.count);
                    break;

                case RpcRequest.UpdateNormals:
                    obj = GetObject(target);
                    FastStructure.ReadArray(obj.GetOrCreateNormalBuffer(), ptr, header.index, header.count);
                    obj.OnUpdateNormalRange(header.index, header.count);
                    break;

                // TODO: ... and so on for UV/weights
                default:
                    Debug.LogWarning($"Unhandled request type {header.type} for {target}");
                    break;
                }

                // TODO: Necessary to count bytes? We won't read anything off this
                // buffer at this point so it's safe to drop the whole thing.
                return(0);
            });

            // Handle any disconnects that may have occured during the read
            if (disconnected)
            {
                OnDisconnectFromBlender();
            }

            Profiler.EndSample();
        }