Exemple #1
0
        /// <summary>
        /// Cleanup any lingering blender data from the scene (viewport cameras, meshes, etc)
        /// </summary>
        private void OnDisconnectFromBlender()
        {
            Debug.Log("Disconnected from Blender");
            IsConnected = false;

            // Clear any messages still queued to send
            messages.ClearQueue();

            // Reset Blender state information
            blenderState = new InteropBlenderState();

            // Clear the scene of any synced data from Blender
            Clear();
        }
Exemple #2
0
        /// <summary>
        /// Connect to a shared memory space hosted by Unity and sync scene data
        /// </summary>
        /// <param name="connectionName">Common name for the shared memory space between Blender and Unity</param>
        public bool Connect(string connectionName, string versionInfo)
        {
            blenderState = new InteropBlenderState
            {
                version = versionInfo
            };

            try
            {
                InteropLogger.Debug($"Connecting to `{connectionName + VIEWPORT_IMAGE_BUFFER}`");

                // Buffer for render data coming from Unity (consume-only)
                pixelsConsumer = new CircularBuffer(connectionName + VIEWPORT_IMAGE_BUFFER);

                InteropLogger.Debug($"Connecting to `{connectionName + UNITY_MESSAGES_BUFFER}` and `{connectionName + BLENDER_MESSAGES_BUFFER}`");

                // Two-way channel between Blender and Unity
                messages = new InteropMessenger();
                messages.ConnectAsSlave(
                    connectionName + UNITY_MESSAGES_BUFFER,
                    connectionName + BLENDER_MESSAGES_BUFFER
                    );
            }
            catch (System.IO.FileNotFoundException)
            {
                // Shared memory space is not valid - Unity may not have started it.
                // This is an error that should be gracefully handled by the UI.
                IsConnectedToSharedMemory = false;
                return(false);
            }

            IsConnectedToSharedMemory = true;

            // Send an initial connect message to let Unity know we're in
            messages.Queue(RpcRequest.Connect, versionInfo, ref blenderState);

            return(true);
        }
Exemple #3
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);
        }
Exemple #4
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();
        }