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"); }
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(); }
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) })); } }
/// <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); }
/// <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> "; // foreach( var err in errors) // { // errorMsg += $"<code>{err.Message}</code> "; // } // 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(); }