Пример #1
0
        public override void UpdateSender(string args)
        {
            var client = JsonConvert.DeserializeObject <dynamic>(args);
            var index  = ClientListWrapper.clients.FindIndex(cl => (string)cl._id == (string)client._id);

            ClientListWrapper.clients[index] = client;

            var myStream = LocalState.FirstOrDefault(st => st.StreamId == (string)client.streamId);

            myStream.Name = (string)client.name;

            Queue.Add(new Action(() =>
            {
                using (Transaction t = new Transaction(CurrentDoc.Document, "Update Speckle Sender"))
                {
                    t.Start();
                    SpeckleStateManager.WriteState(CurrentDoc.Document, LocalState);
                    SpeckleClientsStorageManager.WriteClients(CurrentDoc.Document, ClientListWrapper);
                    t.Commit();
                }
            }));
            Executor.Raise();

            ISelectionFilter filter = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(client.filter), GetFilterType(client.filter.Type.ToString()));

            GetSelectionFilterObjects(filter, client._id.ToString(), client.streamId.ToString());

            SpeckleTelemetry.RecordStreamUpdated("Revit");
        }
Пример #2
0
        public override void AddSelectionToSender(string args)
        {
            var client = JsonConvert.DeserializeObject <dynamic>(args);

            var selectionIds = CurrentDoc.Selection.GetElementIds().Select(id => CurrentDoc.Document.GetElement(id).UniqueId);

            // LOCAL STATE management
            var spkObjectsToAdd = selectionIds.Select(id =>
            {
                var temp = new SpeckleObject();
                temp.Properties["revitUniqueId"] = id;
                temp.Properties["__type"]        = "Sent Object";
                return(temp);
            });

            var myStream = LocalState.FirstOrDefault(st => st.StreamId == (string)client.streamId);
            var added    = 0;

            foreach (var obj in spkObjectsToAdd)
            {
                var ind = myStream.Objects.FindIndex(o => (string)o.Properties["revitUniqueId"] == (string)obj.Properties["revitUniqueId"]);
                if (ind == -1)
                {
                    myStream.Objects.Add(obj);
                    added++;
                }
            }

            var myClient = ClientListWrapper.clients.FirstOrDefault(cl => (string)cl._id == (string)client._id);

            myClient.objects = JsonConvert.DeserializeObject <dynamic>(JsonConvert.SerializeObject(myStream.Objects));

            // Persist state and clients to revit file
            Queue.Add(new Action(() =>
            {
                using (Transaction t = new Transaction(CurrentDoc.Document, "Adding Speckle Receiver"))
                {
                    t.Start();
                    SpeckleStateManager.WriteState(CurrentDoc.Document, LocalState);
                    SpeckleClientsStorageManager.WriteClients(CurrentDoc.Document, ClientListWrapper);
                    t.Commit();
                }
            }));
            Executor.Raise();

            if (added != 0)
            {
                NotifyUi("update-client", JsonConvert.SerializeObject(new
                {
                    _id     = client._id,
                    expired = true,
                    objects = myClient.objects,
                    message = String.Format("You have added {0} objects from this sender.", added)
                }));
            }
            //throw new NotImplementedException();
        }
Пример #3
0
        public override void RemoveSelectionFromSender(string args)
        {
            var client   = JsonConvert.DeserializeObject <dynamic>(args);
            var myStream = LocalState.FirstOrDefault(st => st.StreamId == (string)client.streamId);
            var myClient = ClientListWrapper.clients.FirstOrDefault(cl => (string)cl._id == (string)client._id);

            var selectionIds = CurrentDoc.Selection.GetElementIds().Select(id => CurrentDoc.Document.GetElement(id).UniqueId);
            var removed      = 0;

            foreach (var revitUniqueId in selectionIds)
            {
                var index = myStream.Objects.FindIndex(o => (string)o.Properties["revitUniqueId"] == revitUniqueId);
                if (index == -1)
                {
                    continue;
                }
                myStream.Objects.RemoveAt(index);
                removed++;
            }

            myClient.objects = JsonConvert.DeserializeObject <dynamic>(JsonConvert.SerializeObject(myStream.Objects));

            // Persist state and clients to revit file
            Queue.Add(new Action(() =>
            {
                using (Transaction t = new Transaction(CurrentDoc.Document, "Adding Speckle Receiver"))
                {
                    t.Start();
                    SpeckleStateManager.WriteState(CurrentDoc.Document, LocalState);
                    SpeckleClientsStorageManager.WriteClients(CurrentDoc.Document, ClientListWrapper);
                    t.Commit();
                }
            }));
            Executor.Raise();

            if (removed != 0)
            {
                NotifyUi("update-client", JsonConvert.SerializeObject(new
                {
                    _id     = client._id,
                    expired = true,
                    objects = myClient.objects,
                    message = String.Format("You have removed {0} objects from this sender.", removed)
                }));
            }
        }
Пример #4
0
        /// <summary>
        /// Given the filter in use by a stream returns the document elements that match it
        /// </summary>
        /// <returns></returns>
        private IEnumerable <SpeckleObject> GetSelectionFilterObjects(ISelectionFilter filter, string clientId, string streamId)
        {
            var doc = CurrentDoc.Document;
            IEnumerable <SpeckleObject> objects = new List <SpeckleObject>();

            var selectionIds = new List <string>();

            if (filter.Name == "Selection")
            {
                var selFilter = filter as ElementsSelectionFilter;
                selectionIds = selFilter.Selection;
            }
            else if (filter.Name == "Category")
            {
                var catFilter  = filter as ListSelectionFilter;
                var bics       = new List <BuiltInCategory>();
                var categories = Globals.GetCategories(doc);
                IList <ElementFilter> elementFilters = new List <ElementFilter>();

                foreach (var cat in catFilter.Selection)
                {
                    elementFilters.Add(new ElementCategoryFilter(categories[cat].Id));
                }
                LogicalOrFilter categoryFilter = new LogicalOrFilter(elementFilters);

                selectionIds = new FilteredElementCollector(doc)
                               .WhereElementIsNotElementType()
                               .WhereElementIsViewIndependent()
                               .WherePasses(categoryFilter)
                               .Select(x => x.UniqueId).ToList();
            }
            else if (filter.Name == "View")
            {
                var viewFilter = filter as ListSelectionFilter;

                var views = new FilteredElementCollector(doc)
                            .WhereElementIsNotElementType()
                            .OfClass(typeof(View))
                            .Where(x => viewFilter.Selection.Contains(x.Name));

                foreach (var view in views)
                {
                    var ids = new FilteredElementCollector(doc, view.Id)
                              .WhereElementIsNotElementType()
                              .WhereElementIsViewIndependent()
                              .Where(x => x.IsPhysicalElement())
                              .Select(x => x.UniqueId).ToList();

                    selectionIds = selectionIds.Union(ids).ToList();
                }
            }
            else if (filter.Name == "Parameter")
            {
                try
                {
                    var propFilter = filter as PropertySelectionFilter;
                    var query      = new FilteredElementCollector(doc)
                                     .WhereElementIsNotElementType()
                                     .WhereElementIsNotElementType()
                                     .WhereElementIsViewIndependent()
                                     .Where(x => x.IsPhysicalElement())
                                     .Where(fi => fi.LookupParameter(propFilter.PropertyName) != null);

                    propFilter.PropertyValue = propFilter.PropertyValue.ToLowerInvariant();

                    switch (propFilter.PropertyOperator)
                    {
                    case "equals":
                        query = query.Where(fi => GetStringValue(fi.LookupParameter(propFilter.PropertyName)) == propFilter.PropertyValue);
                        break;

                    case "contains":
                        query = query.Where(fi => GetStringValue(fi.LookupParameter(propFilter.PropertyName)).Contains(propFilter.PropertyValue));
                        break;

                    case "is greater than":
                        query = query.Where(fi => UnitUtils.ConvertFromInternalUnits(
                                                fi.LookupParameter(propFilter.PropertyName).AsDouble(),
                                                fi.LookupParameter(propFilter.PropertyName).DisplayUnitType) > double.Parse(propFilter.PropertyValue));
                        break;

                    case "is less than":
                        query = query.Where(fi => UnitUtils.ConvertFromInternalUnits(
                                                fi.LookupParameter(propFilter.PropertyName).AsDouble(),
                                                fi.LookupParameter(propFilter.PropertyName).DisplayUnitType) < double.Parse(propFilter.PropertyValue));
                        break;

                    default:
                        break;
                    }

                    selectionIds = query.Select(x => x.UniqueId).ToList();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }

            // LOCAL STATE management
            objects = selectionIds.Select(id =>
            {
                var temp = new SpeckleObject();
                temp.Properties["revitUniqueId"] = id;
                temp.Properties["__type"]        = "Sent Object";
                return(temp);
            });


            var myStream = LocalState.FirstOrDefault(st => st.StreamId == streamId);

            myStream.Objects.Clear();
            myStream.Objects.AddRange(objects);

            var myClient = ClientListWrapper.clients.FirstOrDefault(cl => (string)cl._id == (string)clientId);

            myClient.objects = JsonConvert.DeserializeObject <dynamic>(JsonConvert.SerializeObject(myStream.Objects));

            // Persist state and clients to revit file
            Queue.Add(new Action(() =>
            {
                using (Transaction t = new Transaction(CurrentDoc.Document, "Update local storage"))
                {
                    t.Start();
                    SpeckleStateManager.WriteState(CurrentDoc.Document, LocalState);
                    SpeckleClientsStorageManager.WriteClients(CurrentDoc.Document, ClientListWrapper);
                    t.Commit();
                }
            }));
            Executor.Raise();
            var plural = objects.Count() == 1 ? "" : "s";

            if (objects.Count() != 0)
            {
                NotifyUi("update-client", JsonConvert.SerializeObject(new
                {
                    _id     = clientId,
                    expired = true,
                    objects = myClient.objects,
                    //message = $"You have added {objects.Count()} object{plural} to this sender."
                }));
            }

            return(objects);
        }
Пример #5
0
        /// <summary>
        /// This function will bake the objects in the given receiver. Behaviour:
        /// 1) Fresh bake: objects are created
        /// 2) Diff bake: old objects are deleted, any overlapping objects (by applicationId) are either edited or left alone if not marked as having been user modified, new objects are created.
        /// </summary>
        /// <param name="args">Serialised client coming from the ui.</param>
        public override void BakeReceiver(string args)
        {
            var client    = JsonConvert.DeserializeObject <dynamic>(args);
            var apiClient = new SpeckleApiClient((string)client.account.RestApi)
            {
                AuthToken = (string)client.account.Token
            };

            apiClient.ClientType = "Revit";

            //dispatch on the cef window to let progress bar update
            SpeckleWindow.Dispatcher.Invoke(() =>
            {
                NotifyUi("update-client", JsonConvert.SerializeObject(new
                {
                    _id          = (string)client._id,
                    loading      = true,
                    loadingBlurb = "Getting stream from server..."
                }));
            }, System.Windows.Threading.DispatcherPriority.Background);



            var previousStream = LocalState.FirstOrDefault(s => s.StreamId == (string)client.streamId);
            var stream         = apiClient.StreamGetAsync((string)client.streamId, "").Result.Resource;

            InjectScaleInKits(GetScale((string)stream.BaseProperties.units));
            var test = stream.BaseProperties.unitsDictionary;

            if (test != null)
            {
                var secondTest = JsonConvert.DeserializeObject <Dictionary <string, string> >(JsonConvert.SerializeObject(test));
                InjectUnitDictionaryInKits(secondTest);
            }
            else
            {
                InjectUnitDictionaryInKits(null); // make sure it's not there to potentially muddy the waters on other conversions
            }
            // If it's the first time we bake this stream, create a local shadow copy
            if (previousStream == null)
            {
                previousStream = new SpeckleStream()
                {
                    StreamId = stream.StreamId, Objects = new List <SpeckleObject>()
                };
                LocalState.Add(previousStream);
            }

            LocalContext.GetCachedObjects(stream.Objects, (string)client.account.RestApi);
            var payload = stream.Objects.Where(o => o.Type == "Placeholder").Select(obj => obj._id).ToArray();

            // TODO: Orchestrate & save in cache afterwards!
            var objects = apiClient.ObjectGetBulkAsync(payload, "").Result.Resources;

            foreach (var obj in objects)
            {
                stream.Objects[stream.Objects.FindIndex(o => o._id == obj._id)] = obj;
            }

            var(toDelete, ToAddOrMod) = DiffStreamStates(previousStream, stream);

            SpeckleWindow.Dispatcher.Invoke(() =>
            {
                NotifyUi("update-client", JsonConvert.SerializeObject(new
                {
                    _id          = (string)client._id,
                    loading      = true,
                    loadingBlurb = "Deleting " + toDelete.Count() + " objects.",
                    objects      = stream.Objects
                }));
            }, System.Windows.Threading.DispatcherPriority.Background);



            // DELETION OF OLD OBJECTS
            if (toDelete.Count() > 0)
            {
                Queue.Add(new Action(() =>
                {
                    using (Transaction t = new Transaction(CurrentDoc.Document, "Speckle Delete (" + (string)client.streamId + ")"))
                    {
                        t.Start();
                        foreach (var obj in toDelete)
                        {
                            var myObj = previousStream.Objects.FirstOrDefault(o => o._id == obj._id);
                            if (myObj != null)
                            {
                                var elem = CurrentDoc.Document.GetElement(myObj.Properties["revitUniqueId"] as string);
                                CurrentDoc.Document.Delete(elem.Id);
                            }
                        }
                        t.Commit();
                    }
                }));
                Executor.Raise();
            }

            // ADD/MOD/LEAVE ALONE EXISTING OBJECTS

            //if the conversion completely fails, it outputs a speckleerror and it's put in here
            var errors = new List <SpeckleError>();

            //this instead will store errors swallowed by the erroreater class
            Globals.ConversionErrors = new List <SpeckleError>();
            var tempList = new List <SpeckleObject>();

            Queue.Add(new Action(() =>
            {
                using (var t = new Transaction(CurrentDoc.Document, "Speckle Bake"))
                {
                    t.Start();

                    int i = 0;
                    foreach (var mySpkObj in ToAddOrMod)
                    {
                        SpeckleWindow.Dispatcher.Invoke(() =>
                        {
                            NotifyUi("update-client", JsonConvert.SerializeObject(new
                            {
                                _id     = (string)client._id,
                                loading = true,
                                isLoadingIndeterminate = false,
                                loadingProgress        = 1f * i / ToAddOrMod.Count * 100,
                                loadingBlurb           = string.Format("Creating/updating objects: {0} / {1}", i, ToAddOrMod.Count)
                            }));
                        }, System.Windows.Threading.DispatcherPriority.Background);



                        object res;

                        var failOpts = t.GetFailureHandlingOptions();
                        failOpts.SetFailuresPreprocessor(new ErrorEater());
                        t.SetFailureHandlingOptions(failOpts);

                        try
                        {
                            res = SpeckleCore.Converter.Deserialise(obj: mySpkObj, excludeAssebmlies: new string[] { "SpeckleCoreGeometryDynamo", "SpeckleCoreGeometryRevit" });

                            // The converter returns either the converted object, or the original speckle object if it failed to deserialise it.
                            // Hence, we need to create a shadow copy of the baked element only if deserialisation was succesful.
                            if (res is Element)
                            {
                                // creates a shadow copy of the baked object to store in our local state.
                                var myObject = new SpeckleObject()
                                {
                                    Properties = new Dictionary <string, object>()
                                };
                                myObject._id                         = mySpkObj._id;
                                myObject.ApplicationId               = mySpkObj.ApplicationId;
                                myObject.Properties["__type"]        = mySpkObj.Type;
                                myObject.Properties["revitUniqueId"] = ((Element)res).UniqueId;
                                myObject.Properties["revitId"]       = ((Element)res).Id.ToString();
                                myObject.Properties["userModified"]  = false;

                                tempList.Add(myObject);
                            }

                            // TODO: Handle scenario when one object creates more objects.
                            // ie: SpeckleElements wall with a base curve that is a polyline/polycurve
                            if (res is System.Collections.IEnumerable)
                            {
                                int k  = 0;
                                var xx = ((IEnumerable <object>)res).Cast <Element>();
                                foreach (var elm in xx)
                                {
                                    var myObject                         = new SpeckleObject();
                                    myObject._id                         = mySpkObj._id;
                                    myObject.ApplicationId               = mySpkObj.ApplicationId;
                                    myObject.Properties["__type"]        = mySpkObj.Type;
                                    myObject.Properties["revitUniqueId"] = ((Element)elm).UniqueId;
                                    myObject.Properties["revitId"]       = ((Element)elm).Id.ToString();
                                    myObject.Properties["userModified"]  = false;
                                    myObject.Properties["orderIndex"]    = k++; // keeps track of which elm it actually is

                                    tempList.Add(myObject);
                                }
                            }

                            //if( res is SpeckleObject || res == null ) failedToBake++;

                            if (res is SpeckleError)
                            {
                                errors.Add(res as SpeckleError);
                            }
                        }
                        catch (Exception e)
                        {
                            //if(e.Message.Contains("missing"))
                            //failedToBake++;
                            errors.Add(new SpeckleError {
                                Message = e.Message
                            });
                        }


                        i++;
                    }
                    t.Commit();
                }
            }));
            Executor.Raise();


            Queue.Add(new Action(() =>
            {
                SpeckleWindow.Dispatcher.Invoke(() =>
                {
                    NotifyUi("update-client", JsonConvert.SerializeObject(new
                    {
                        _id     = (string)client._id,
                        loading = true,
                        isLoadingIndeterminate = true,
                        loadingBlurb           = string.Format("Updating shadow state.")
                    }));
                }, System.Windows.Threading.DispatcherPriority.Background);



                // set the local state stream's object list, and inject it in the kits, persist it in the doc
                previousStream.Objects = tempList;
                InjectStateInKits();
                using (var t = new Transaction(CurrentDoc.Document, "Speckle State Save"))
                {
                    t.Start();
                    Storage.SpeckleStateManager.WriteState(CurrentDoc.Document, LocalState);
                    t.Commit();
                }

                string errorMsg     = "";
                int failedToConvert = errors.Count();

                //other conversion errors that we are catching
                var additionalErrors = GetAndClearConversionErrors();

                if (additionalErrors != null && additionalErrors.Count > 0)
                {
                    errors.AddRange(additionalErrors);
                }
                errors.AddRange(Globals.ConversionErrors);

                //remove duplicates
                errors = errors.GroupBy(x => x.Message).Select(x => x.First()).ToList();

                if (errors.Any())
                {
                    errorMsg += string.Format("There {0} {1} error{2} ",
                                              errors.Count() == 1 ? "is" : "are",
                                              errors.Count(),
                                              errors.Count() == 1 ? "" : "s");
                    if (failedToConvert > 0)
                    {
                        errorMsg += string.Format("and {0} objects that failed to convert ",
                                                  failedToConvert,
                                                  failedToConvert == 1 ? "" : "s");
                    }

                    errorMsg += "<nobr>" + Globals.GetRandomSadFace() + "</nobr>";
                }

                //if(errors.Any())
                //{
                //  errorMsg += "" +
                //  //errors += "<v-divider></v-divider>" +
                //  "<v-layout row wrap><v-flex xs12>";
                //  //"<strong>Missing families:</strong>&nbsp;&nbsp;";

                //  foreach( var err in errors)
                //  {
                //    errorMsg += $"<code>{err.Message}</code>&nbsp;";
                //  }

                //  errorMsg += "</v-flex></v-layout>";
                //}

                SpeckleWindow.Dispatcher.Invoke(() =>
                {
                    NotifyUi("update-client", JsonConvert.SerializeObject(new
                    {
                        _id     = (string)client._id,
                        loading = false,
                        isLoadingIndeterminate = true,
                        loadingBlurb           = string.Format("Done."),
                        errorMsg,
                        errors
                    }));
                }, System.Windows.Threading.DispatcherPriority.Background);
            }));

            Executor.Raise();
        }