Esempio n. 1
0
        public void BakeLayer(string layerId)
        {
            SpeckleCore.Layer myLayer = Client.Stream.Layers.FirstOrDefault(l => l.Guid == layerId);

            // create or get parent
            string parent = String.Format("{1} | {0}", Client.Stream.StreamId, Client.Stream.Name);

            var parentId = Rhino.RhinoDoc.ActiveDoc.Layers.FindByFullPath(parent, true);

            if (parentId == -1)
            {
                var parentLayer = new Rhino.DocObjects.Layer()
                {
                    Color = System.Drawing.Color.Black,
                    Name  = parent
                };
                parentId = Rhino.RhinoDoc.ActiveDoc.Layers.Add(parentLayer);
            }
            else
            {
                int prev = Rhino.RhinoDoc.ActiveDoc.Layers.FindByFullPath(parent + "::" + myLayer.Name, true);
                if (prev != -1)
                {
                    Rhino.RhinoDoc.ActiveDoc.Layers.Purge(prev, true);
                }
            }

            int theLayerId = Rhino.RhinoDoc.ActiveDoc.Layers.FindByFullPath(parent + "::" + myLayer.Name, true);

            if (theLayerId == -1)
            {
                var layer = new Rhino.DocObjects.Layer()
                {
                    Name          = myLayer.Name,
                    Id            = Guid.Parse(myLayer.Guid),
                    ParentLayerId = Rhino.RhinoDoc.ActiveDoc.Layers[parentId].Id,
                    Color         = GetColorFromLayer(myLayer),
                    IsVisible     = true
                };
                var index = Rhino.RhinoDoc.ActiveDoc.Layers.Add(layer);
                for (int i = ( int )myLayer.StartIndex; i < myLayer.StartIndex + myLayer.ObjectCount; i++)
                {
                    if (Display.Geometry[i] != null)
                    {
                        Rhino.RhinoDoc.ActiveDoc.Objects.Add(Display.Geometry[i], new ObjectAttributes()
                        {
                            LayerIndex = index
                        });
                    }
                }
            }
            Rhino.RhinoDoc.ActiveDoc?.Views.Redraw();
        }
Esempio n. 2
0
        public void ToggleLayerVisibility(string layerId, bool status)
        {
            SpeckleCore.Layer myLayer = Client.Stream.Layers.FirstOrDefault(l => l.Guid == layerId);
            if (myLayer == null)
            {
                throw new Exception("Bloopers. Layer not found.");
            }

            for (int i = ( int )myLayer.StartIndex; i < myLayer.StartIndex + myLayer.ObjectCount; i++)
            {
                Display.VisibleList[i] = status;
            }
            Rhino.RhinoDoc.ActiveDoc?.Views.Redraw();
        }
Esempio n. 3
0
 public System.Drawing.Color GetColorFromLayer(SpeckleCore.Layer layer)
 {
     System.Drawing.Color layerColor = System.Drawing.ColorTranslator.FromHtml("#AEECFD");
     try
     {
         if (layer != null && layer.Properties != null)
         {
             layerColor = System.Drawing.ColorTranslator.FromHtml(layer.Properties.Color.Hex);
         }
     }
     catch
     {
         Debug.WriteLine("Layer '{0}' had no assigned color", layer.Name);
     }
     return(layerColor);
 }
Esempio n. 4
0
        public void ToggleLayerHover(string layerId, bool status)
        {
            SpeckleCore.Layer myLayer = Client.Stream.Layers.FirstOrDefault(l => l.Guid == layerId);
            if (myLayer == null)
            {
                throw new Exception("Bloopers. Layer not found.");
            }

            if (status)
            {
                Display.HoverRange = new Interval(( double )myLayer.StartIndex, ( double )(myLayer.StartIndex + myLayer.ObjectCount));
            }
            else
            {
                Display.HoverRange = null;
            }
            Rhino.RhinoDoc.ActiveDoc?.Views.Redraw();
        }
Esempio n. 5
0
        public async void SendStaggeredUpdate(bool force = false)
        {
            if (Paused && !force)
            {
                Context.NotifySpeckleFrame("client-expired", StreamId, "");
                return;
            }
            else
            {
                // create a clone
                var cloneResult = Client.StreamCloneAsync(StreamId).Result;
                Client.Stream.Children.Add(cloneResult.Clone.StreamId);

                Client.BroadcastMessage("stream", StreamId, new { eventType = "update-children" });
            }

            if (IsSendingUpdate)
            {
                Expired = true;
                return;
            }

            IsSendingUpdate = true;

            Context.NotifySpeckleFrame("client-is-loading", StreamId, "");

            var objs = RhinoDoc.ActiveDoc.Objects.FindByUserString("spk_" + this.StreamId, "*", false).OrderBy(obj => obj.Attributes.LayerIndex);

            Context.NotifySpeckleFrame("client-progress-message", StreamId, "Converting " + objs.Count() + " objects...");

            // layer list creation
            var pLayers = new List <SpeckleCore.Layer>();
            int lindex = -1, count = 0, orderIndex = 0;

            foreach (RhinoObject obj in objs)
            {
                Rhino.DocObjects.Layer layer = RhinoDoc.ActiveDoc.Layers[obj.Attributes.LayerIndex];
                if (lindex != obj.Attributes.LayerIndex)
                {
                    var spkLayer = new SpeckleCore.Layer()
                    {
                        Name        = layer.FullPath,
                        Guid        = layer.Id.ToString(),
                        ObjectCount = 1,
                        StartIndex  = count,
                        OrderIndex  = orderIndex++,
                        Properties  = new LayerProperties()
                        {
                            Color = new SpeckleCore.SpeckleBaseColor()
                            {
                                A = 1, Hex = System.Drawing.ColorTranslator.ToHtml(layer.Color)
                            },
                        }
                    };

                    pLayers.Add(spkLayer);
                    lindex = obj.Attributes.LayerIndex;
                }
                else
                {
                    var spkl = pLayers.FirstOrDefault(pl => pl.Name == layer.FullPath);
                    spkl.ObjectCount++;
                }

                count++;
            }

            // convert objects
            var convertedObjects = new List <SpeckleObject>();

            foreach (RhinoObject obj in objs)
            {
                var myObj = Converter.Serialise(obj.Geometry);
                myObj.ApplicationId = obj.Id.ToString();
                convertedObjects.Add(myObj);
            }

            LocalContext.PruneExistingObjects(convertedObjects, Client.BaseUrl);

            List <SpeckleObject> persistedObjects = new List <SpeckleObject>();

            if (convertedObjects.Count(obj => obj.Type == "Placeholder") != convertedObjects.Count)
            {
                // create the update payloads
                count = 0;
                var  objectUpdatePayloads = new List <List <SpeckleObject> >();
                long totalBucketSize      = 0;
                long currentBucketSize    = 0;
                var  currentBucketObjects = new List <SpeckleObject>();
                var  allObjects           = new List <SpeckleObject>();
                foreach (SpeckleObject convertedObject in convertedObjects)
                {
                    if (count++ % 100 == 0)
                    {
                        Context.NotifySpeckleFrame("client-progress-message", StreamId, "Converted " + count + " objects out of " + objs.Count() + ".");
                    }

                    // size checking & bulk object creation payloads creation
                    long size = Converter.getBytes(convertedObject).Length;
                    currentBucketSize += size;
                    totalBucketSize   += size;
                    currentBucketObjects.Add(convertedObject);

                    // Object is too big?
                    if (size > 2e6)
                    {
                        Context.NotifySpeckleFrame("client-error", StreamId, JsonConvert.SerializeObject("This stream contains a super big object. These will fail. Sorry for the bad error message - we're working on improving this."));
                        currentBucketObjects.Remove(convertedObject);
                    }

                    if (currentBucketSize > 5e5) // restrict max to ~500kb; should it be user config? anyway these functions should go into core. at one point.
                    {
                        Debug.WriteLine("Reached payload limit. Making a new one, current  #: " + objectUpdatePayloads.Count);
                        objectUpdatePayloads.Add(currentBucketObjects);
                        currentBucketObjects = new List <SpeckleObject>();
                        currentBucketSize    = 0;
                    }
                }

                // add in the last bucket
                if (currentBucketObjects.Count > 0)
                {
                    objectUpdatePayloads.Add(currentBucketObjects);
                }

                Debug.WriteLine("Finished, payload object update count is: " + objectUpdatePayloads.Count + " total bucket size is (kb) " + totalBucketSize / 1000);

                // create bulk object creation tasks
                int k = 0;
                List <ResponseObject> responses = new List <ResponseObject>();
                foreach (var payload in objectUpdatePayloads)
                {
                    Context.NotifySpeckleFrame("client-progress-message", StreamId, String.Format("Sending payload {0} out of {1}", k++, objectUpdatePayloads.Count));
                    try
                    {
                        var objResponse = await Client.ObjectCreateAsync(payload);

                        responses.Add(objResponse);
                        persistedObjects.AddRange(objResponse.Resources);

                        int m = 0;
                        foreach (var oL in payload)
                        {
                            oL._id = objResponse.Resources[m++]._id;
                        }

                        // push sent objects in the cache non-blocking
                        Task.Run(() =>
                        {
                            foreach (var oL in payload)
                            {
                                if (oL.Type != "Placeholder")
                                {
                                    LocalContext.AddSentObject(oL, Client.BaseUrl);
                                }
                            }
                        });
                    }
                    catch (Exception err)
                    {
                        Context.NotifySpeckleFrame("client-error", Client.Stream.StreamId, JsonConvert.SerializeObject(err.Message));
                        Context.NotifySpeckleFrame("client-done-loading", StreamId, "");
                        IsSendingUpdate = false;
                        return;
                    }
                }
            }
            else
            {
                persistedObjects = convertedObjects;
            }

            Context.NotifySpeckleFrame("client-progress-message", StreamId, "Updating stream...");

            // finalise layer creation
            foreach (var layer in pLayers)
            {
                layer.Topology = "0-" + layer.ObjectCount + " ";
            }

            // create placeholders for stream update payload
            List <SpeckleObject> placeholders = new List <SpeckleObject>();

            //foreach ( var myResponse in responses )
            foreach (var obj in persistedObjects)
            {
                placeholders.Add(new SpecklePlaceholder()
                {
                    _id = obj._id
                });
            }

            // create stream update payload
            SpeckleStream streamUpdatePayload = new SpeckleStream();

            streamUpdatePayload.Layers  = pLayers;
            streamUpdatePayload.Objects = placeholders;
            streamUpdatePayload.Name    = Client.Stream.Name;

            // set some base properties (will be overwritten)
            var baseProps = new Dictionary <string, object>();

            baseProps["units"]                 = RhinoDoc.ActiveDoc.ModelUnitSystem.ToString();
            baseProps["tolerance"]             = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;
            baseProps["angleTolerance"]        = RhinoDoc.ActiveDoc.ModelAngleToleranceRadians;
            streamUpdatePayload.BaseProperties = baseProps;

            // update the stream
            ResponseBase response = null;

            try
            {
                response = await Client.StreamUpdateAsync(Client.Stream.StreamId, streamUpdatePayload);
            }
            catch (Exception err)
            {
                Context.NotifySpeckleFrame("client-error", Client.Stream.StreamId, JsonConvert.SerializeObject(err.Message));
                IsSendingUpdate = false;
                return;
            }

            // emit  events, etc.
            Client.Stream.Layers  = streamUpdatePayload.Layers.ToList();
            Client.Stream.Objects = placeholders;

            Context.NotifySpeckleFrame("client-metadata-update", StreamId, Client.Stream.ToJson());
            Context.NotifySpeckleFrame("client-done-loading", StreamId, "");

            Client.BroadcastMessage("stream", StreamId, new { eventType = "update-global" });

            IsSendingUpdate = false;
            if (Expired)
            {
                DataSender.Start();
            }
            Expired = false;
        }
        // TODO: This method, or an abstracted version of it, should move to Speckle Core.
        public async void SendStaggeredUpdate(bool force = false)
        {
            if (Paused && !force)
            {
                Context.NotifySpeckleFrame("client-expired", StreamId, "");
                return;
            }

            if (IsSendingUpdate)
            {
                Expired = true;
                return;
            }

            IsSendingUpdate = true;

            Context.NotifySpeckleFrame("client-is-loading", StreamId, "");

            var objs = RhinoDoc.ActiveDoc.Objects.FindByUserString("spk_" + this.StreamId, "*", false).OrderBy(obj => obj.Attributes.LayerIndex);

            Context.NotifySpeckleFrame("client-progress-message", StreamId, "Converting " + objs.Count() + " objects...");

            List <SpeckleCore.Layer>     pLayers              = new List <SpeckleCore.Layer>();
            List <SpeckleObject>         convertedObjects     = new List <SpeckleObject>();
            List <List <SpeckleObject> > objectUpdatePayloads = new List <List <SpeckleObject> >();

            long totalBucketSize   = 0;
            long currentBucketSize = 0;
            List <SpeckleObject> currentBucketObjects = new List <SpeckleObject>();
            List <SpeckleObject> allObjects           = new List <SpeckleObject>();

            int lindex = -1, count = 0, orderIndex = 0;

            foreach (RhinoObject obj in objs)
            {
                // layer list creation
                Rhino.DocObjects.Layer layer = RhinoDoc.ActiveDoc.Layers[obj.Attributes.LayerIndex];
                if (lindex != obj.Attributes.LayerIndex)
                {
                    var spkLayer = new SpeckleCore.Layer()
                    {
                        Name        = layer.FullPath,
                        Guid        = layer.Id.ToString(),
                        ObjectCount = 1,
                        StartIndex  = count,
                        OrderIndex  = orderIndex++,
                        Properties  = new LayerProperties()
                        {
                            Color = new SpeckleCore.SpeckleBaseColor()
                            {
                                A = 1, Hex = System.Drawing.ColorTranslator.ToHtml(layer.Color)
                            },
                        }
                    };

                    pLayers.Add(spkLayer);
                    lindex = obj.Attributes.LayerIndex;
                }
                else
                {
                    var spkl = pLayers.FirstOrDefault(pl => pl.Name == layer.FullPath);
                    spkl.ObjectCount++;
                }

                count++;

                // object conversion
                SpeckleObject convertedObject;

                convertedObject = Converter.Serialise(obj.Geometry);
                convertedObject.ApplicationId = obj.Id.ToString();
                allObjects.Add(convertedObject);

                if (count % 10 == 0)
                {
                    Context.NotifySpeckleFrame("client-progress-message", StreamId, "Converted " + count + " objects out of " + objs.Count() + ".");
                }

                // check cache and see what the response from the server is when sending placeholders
                // in the ObjectCreateBulkAsyncRoute
                if (Context.SpeckleObjectCache.ContainsKey(convertedObject.Hash))
                {
                    convertedObject = new SpecklePlaceholder()
                    {
                        Hash = convertedObject.Hash, _id = Context.SpeckleObjectCache[convertedObject.Hash]._id, ApplicationId = Context.SpeckleObjectCache[convertedObject.Hash].ApplicationId
                    };
                }

                // size checking & bulk object creation payloads creation
                long size = Converter.getBytes(convertedObject).Length;
                currentBucketSize += size;
                totalBucketSize   += size;
                currentBucketObjects.Add(convertedObject);

                if (currentBucketSize > 2e6)
                {
                    // means we're around fooking bazillion mb of an upload. FAIL FAIL FAIL
                    Context.NotifySpeckleFrame("client-error", StreamId, JsonConvert.SerializeObject("This stream contains a super big object. These are not supported yet :("));
                    Context.NotifySpeckleFrame("client-done-loading", StreamId, "");
                    IsSendingUpdate = false;
                    return;
                }

                if (currentBucketSize > 5e5) // restrict max to ~500kb; should it be user config? anyway these functions should go into core. at one point.
                {
                    Debug.WriteLine("Reached payload limit. Making a new one, current  #: " + objectUpdatePayloads.Count);
                    objectUpdatePayloads.Add(currentBucketObjects);
                    currentBucketObjects = new List <SpeckleObject>();
                    currentBucketSize    = 0;
                }

                // catch overflows early
                if (totalBucketSize >= 50e6)
                {
                    Context.NotifySpeckleFrame("client-error", StreamId, JsonConvert.SerializeObject("This is a humongous update, in the range of ~50mb. For now, create more streams instead of just one massive one! Updates will be faster and snappier, and you can combine them back together at the other end easier. " + totalBucketSize / 1000 + "(kb)"));
                    IsSendingUpdate = false;
                    Context.NotifySpeckleFrame("client-done-loading", StreamId, "");
                    return;
                }
            }

            // last bucket
            if (currentBucketObjects.Count > 0)
            {
                objectUpdatePayloads.Add(currentBucketObjects);
            }

            Debug.WriteLine("Finished, payload object update count is: " + objectUpdatePayloads.Count + " total bucket size is (kb) " + totalBucketSize / 1000);

            if (objectUpdatePayloads.Count > 100 || totalBucketSize >= 50e6)
            {
                // means we're around fooking bazillion mb of an upload. FAIL FAIL FAIL
                Context.NotifySpeckleFrame("client-error", StreamId, JsonConvert.SerializeObject("This is a humongous update, in the range of ~50mb. For now, create more streams instead of just one massive one! Updates will be faster and snappier, and you can combine them back together at the other end easier. " + totalBucketSize / 1000 + "(kb)"));
                IsSendingUpdate = false;
                Context.NotifySpeckleFrame("client-done-loading", StreamId, "");
                return;
            }

            // create bulk object creation tasks
            int k = 0;
            List <ResponseObject> responses = new List <ResponseObject>();

            foreach (var payload in objectUpdatePayloads)
            {
                Context.NotifySpeckleFrame("client-progress-message", StreamId, String.Format("Sending payload {0} out of {1}", k++, objectUpdatePayloads.Count));
                try
                {
                    responses.Add(await Client.ObjectCreateAsync(payload));
                }
                catch (Exception err)
                {
                    Context.NotifySpeckleFrame("client-error", Client.Stream.StreamId, JsonConvert.SerializeObject(err.Message));
                    Context.NotifySpeckleFrame("client-done-loading", StreamId, "");
                    IsSendingUpdate = false;
                    return;
                }
            }

            Context.NotifySpeckleFrame("client-progress-message", StreamId, "Updating stream...");

            // finalise layer creation
            foreach (var layer in pLayers)
            {
                layer.Topology = "0-" + layer.ObjectCount + " ";
            }

            // create placeholders for stream update payload
            List <SpeckleObject> placeholders = new List <SpeckleObject>();
            int m = 0;

            foreach (var myResponse in responses)
            {
                foreach (var obj in myResponse.Resources)
                {
                    placeholders.Add(new SpecklePlaceholder()
                    {
                        _id = obj._id, ApplicationId = allObjects[m++].ApplicationId
                    });
                }
            }

            // create stream update payload
            SpeckleStream streamUpdatePayload = new SpeckleStream();

            streamUpdatePayload.Layers  = pLayers;
            streamUpdatePayload.Objects = placeholders;
            streamUpdatePayload.Name    = Client.Stream.Name;

            // set some base properties (will be overwritten)
            var baseProps = new Dictionary <string, object>();

            baseProps["units"]                 = RhinoDoc.ActiveDoc.ModelUnitSystem.ToString();
            baseProps["tolerance"]             = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;
            baseProps["angleTolerance"]        = RhinoDoc.ActiveDoc.ModelAngleToleranceRadians;
            streamUpdatePayload.BaseProperties = baseProps;

            // push it to the server yo!
            ResponseBase response = null;

            try
            {
                response = await Client.StreamUpdateAsync(Client.Stream.StreamId, streamUpdatePayload);
            }
            catch (Exception err)
            {
                Context.NotifySpeckleFrame("client-error", Client.Stream.StreamId, JsonConvert.SerializeObject(err.Message));
                IsSendingUpdate = false;
                return;
            }

            // put the objects in the cache
            int l = 0;

            foreach (var obj in streamUpdatePayload.Objects)
            {
                obj._id = placeholders[l]._id;
                Context.SpeckleObjectCache[allObjects[l].Hash] = placeholders[l];
                l++;
            }

            // emit  events, etc.
            Client.Stream.Layers  = streamUpdatePayload.Layers.ToList();
            Client.Stream.Objects = placeholders;

            Context.NotifySpeckleFrame("client-metadata-update", StreamId, Client.Stream.ToJson());
            Context.NotifySpeckleFrame("client-done-loading", StreamId, "");

            Client.BroadcastMessage(new { eventType = "update-global" });

            IsSendingUpdate = false;
            if (Expired)
            {
                DataSender.Start();
            }
            Expired = false;
        }
Esempio n. 7
0
    public async void UpdateGlobal()
    {
        bRefreshingDisplay = true;

        var streamGetResponse = await Client.StreamGetAsync(Client.StreamId, null);

        if (streamGetResponse.Success == false)
        {
            Debug.Log(streamGetResponse.Message); // TODO: Actually handle this
        }

        Client.Stream = streamGetResponse.Resource; // This is gross of the C# API

        Debug.Log("Getting objects....");
        var getObjectResult = await Client.ObjectGetBulkAsync(Client.Stream.Objects.Select(obj => obj._id).ToArray(), null); // TODO: Check if ObjectGetBulkAsync returns objects in a corresponding order. If it does, the next little bit can be simplified

        Dictionary <string, SpeckleCore.SpeckleObject> ObjectCache = getObjectResult.Resources.ToDictionary(speckleObject => speckleObject._id);

        SpeckleObjects = Client.Stream.Objects.Select(speckleObject => ObjectCache[speckleObject._id]).ToList();

        // Remove old layers
        foreach (SpeckleCore.Layer layer in Layers.Keys.Where(layer => Client.Stream.Layers.Where(newLayer => newLayer.Guid != layer.Guid).Count() > 0).ToList()) // ToList is required because we're modifying Layers, I think
        {
            Destroy(Layers[layer]);
            Layers.Remove(layer);
        }

        // Add new layers
        foreach (SpeckleCore.Layer layer in Client.Stream.Layers.Where(layer => !Layers.ContainsKey(layer)).ToList())
        {
            Layers[layer] = new GameObject(layer.Name);
            Layers[layer].transform.SetParent(rootGameObject.transform);
        }

        // Mark all existing objects
        foreach (UnitySpeckleObjectData usod in rootGameObject.GetComponentsInChildren <UnitySpeckleObjectData>())
        {
            usod.LayerName = null;
        }

        // Create new objects
        for (int i = 0; i < SpeckleObjects.Count; i++)
        {
            SpeckleCore.Layer layer       = LayerFromIndex(i);
            GameObject        layerObject = Layers[layer];
            GameObject        gameObject  = (GameObject)SpeckleCore.Converter.Deserialise(SpeckleObjects[i]); // TODO: This creates a new game object even if one already exists. It should reuse objects which already exist
            // TODO: The more fundamental issue is that checking which layer an object is in is tricky. Perhaps layers map more naturally to Unity's tags.

            gameObject.GetComponent <UnitySpeckleObjectData>().LayerName = layer.Name;
            gameObject.transform.SetParent(layerObject.transform);
        }

        // Destroy all objects which are still marked
        foreach (UnitySpeckleObjectData usod in rootGameObject.GetComponentsInChildren <UnitySpeckleObjectData>())
        {
            if (usod.LayerName == null)
            {
                Destroy(usod.gameObject);
            }
        }

        bRefreshingDisplay = false;
        transform.GetComponent <UnitySpeckle>().OnUpdateReceived.Invoke(this);
    }