/// <summary> /// Mutate the name of the level /// </summary> /// <param name="name"> the name we want to set the level to have</param> /// <param name="oldname"> the oldname we tried to set this level to in the past, /// we retrieve this from trace</param> private void InternalSetName(string oldname, string name) { if (String.IsNullOrEmpty(name) || string.CompareOrdinal(InternalLevel.Name, name) == 0 || string.CompareOrdinal(oldname, name) == 0) { return; } //make a copy of the string var originalInputName = name; //Check to see whether there is an existing level with the same name var levels = ElementQueries.GetAllLevels(); while (levels.Any(x => string.CompareOrdinal(x.Name, name) == 0)) { //Update the level name Revit.Elements.InternalUtilities.ElementUtils.UpdateLevelName(ref name); } TransactionManager.Instance.EnsureInTransaction(Document); this.InternalLevel.Name = name; var updatedTraceData = new LevelTraceData(this, originalInputName); ElementBinder.SetRawDataForTrace(updatedTraceData); TransactionManager.Instance.TransactionTaskDone(); }
/// <summary> /// Initialize a DirectShape element /// </summary> private void InitDirectShape(DesignScriptEntity shapeReference, string shapeName, Category category, Material material) { //Phase 1 - Check to see if a DirectShape exists in trace and should be rebound var oldShape = ElementBinder.GetElementAndTraceData <Autodesk.Revit.DB.DirectShape, DirectShapeState>(Document); //There was a oldDirectShape, rebind to that if (oldShape != null) { //set the directshape element this.InternalSetDirectShape(oldShape.Item1); //if the cateogryID has changed, we cannot continue to rebind and instead //will make a new directShape if (category.Id == this.InternalElement.Category.Id.IntegerValue) { //set the shape geometry of the directshape, this method passes in the actual input geo //and checks the directShapeState object at the elementId key in the input geo tags dictionary. //this check is used to determine if the geometry should be updated, this is done by checking //the sync guid in the DirectShapeState (a guid that is generated when geometry changes on //the revit element. //we also check the material, if it's different than the currently assigned material //then we need to rebuild the geo so that a new material is applied // this.InternalSetShape(shapeReference, new ElementId(material.Id), oldShape.Item2.syncId); this.InternalSetName(shapeReference, shapeName, material, category); return; } } //Phase 2- There was no existing shape, create one TransactionManager.Instance.EnsureInTransaction(Document); Autodesk.Revit.DB.DirectShape ds; //generate the geometry correctly depending on the type of geo var tessellatedShape = GenerateTessellatedGeo(shapeReference, new ElementId(material.Id)); //actually construct the directshape revit element ds = NewDirectShape(tessellatedShape, Document, new ElementId(category.Id), DirectShape.DYNAMO_DIRECTSHAPE_APP_GUID.ToString(), shapeName); InternalSetDirectShape(ds); InternalSetName(shapeReference, shapeName, material, category); //generate a new syncId for trace var traceData = new DirectShapeState(this, Guid.NewGuid().ToString(), new ElementId(material.Id)); //add the elementID:tracedata to the tags dictionary on the real protogeometry input shapeReference.Tags.AddTag(this.InternalElementId.ToString(), traceData); TransactionManager.Instance.TransactionTaskDone(); ElementBinder.SetRawDataForTrace(traceData); }
/// <summary> /// Set the SpatialFieldManager and PrimitiveId in Thread Local Storage /// </summary> /// <param name="manager"></param> /// <param name="primitiveId"></param> protected void SetElementAndPrimitiveIdForTrace(SpatialFieldManager manager, int primitiveId) { if (manager == null) { throw new Exception(); } SpmPrimitiveIdPair idPair = new SpmPrimitiveIdPair(); idPair.SpatialFieldManagerID = manager.Id.IntegerValue; idPair.PrimitiveID = primitiveId; ElementBinder.SetRawDataForTrace(idPair); }
/// <summary> /// Handling exceptions when calling the initializing function /// </summary> /// <param name="init"></param> protected void SafeInit(Action init) { TransactionManager.Instance.EnsureInTransaction(DocumentManager.Instance.CurrentDBDocument); var elementManager = ElementIDLifecycleManager <int> .GetInstance(); var element = ElementBinder.GetElementFromTrace <Autodesk.Revit.DB.Element>(Document); int count = 0; int id = 0; if (null != element) { id = element.Id.IntegerValue; count = elementManager.GetRegisteredCount(id); } try { init(); } catch (Exception e) { //If the element is newly created and bound but the creation is aborted because //of an exception, it need to be unregistered. if (element == null && InternalElementId != null) { elementManager.UnRegisterAssociation(Id, this); internalId = null; throw e; } else if (element != null) { //If the internal element has already been bound, and if the registered count has increased, //it need to be unregistered. if (elementManager.GetRegisteredCount(id) == count + 1) { elementManager.UnRegisterAssociation(Id, this); internalId = null; } //It means that the updating operation failed, an attemption of making a new element is made. ElementBinder.SetRawDataForTrace(null); SafeInit(init); } else { throw e; } } }
/// <summary> /// Set the SpatialFieldManager and PrimitiveId in Thread Local Storage /// </summary> /// <param name="manager"></param> /// <param name="keyValues"></param> protected void SetElementAndRefPrimitiveIdsForTrace(SpatialFieldManager manager, Dictionary <Reference, int> keyValues) { if (manager == null) { throw new Exception(); } var idPair = new SpmRefPrimitiveIdListPair { SpatialFieldManagerID = manager.Id.IntegerValue, RefIdPairs = keyValues }; ElementBinder.SetRawDataForTrace(idPair); }
/// <summary> /// Set the SpatialFieldManager and PrimitiveId in Thread Local Storage /// </summary> /// <param name="manager"></param> /// <param name="primitiveIds"></param> protected void SetElementAndPrimitiveIdsForTrace(SpatialFieldManager manager, List <int> primitiveIds) { if (manager == null) { throw new Exception(); } var idPair = new SpmPrimitiveIdPair { SpatialFieldManagerID = manager.Id.IntegerValue, PrimitiveIds = primitiveIds }; ElementBinder.SetRawDataForTrace(idPair); }
public void RawTraceInteractionTest() { var elementId = new SerializableId { IntID = 42, StringID = "{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}" }; //Raw write ElementBinder.SetRawDataForTrace(elementId); elementId = null; //Readback elementId = (SerializableId)ElementBinder.GetRawDataFromTrace(); Assert.IsTrue(elementId.IntID == 42); Assert.IsTrue(elementId.StringID == "{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}"); }
/// <summary> /// Sets the internalDirectShape's shape to point to some geometry, /// this method also generates tessellated geometry from the protogeometry object /// and sets the material of the generated Revit faces /// </summary> private void InternalSetShape(DesignScriptEntity shapeReference, ElementId materialId, string currentSyncId) { //if the elementID for the current directShape revitElement exists on the input Geometry AND //the value stored at that key is equal to the materialId we're trying to set AND //the previousState's syncId (in the tags dictionary) equals the current syncId (from trace) //then we do not need to regenerate //first lookup the state on the input geometry var previousState = shapeReference.Tags.LookupTag(this.InternalElementId.ToString()) as DirectShapeState; //then compare values if (previousState != null && previousState.materialId == materialId.IntegerValue && previousState.syncId == currentSyncId) { return; } TransactionManager.Instance.EnsureInTransaction(Document); var tessellatedShape = GenerateTessellatedGeo(shapeReference, materialId); this.InternalDirectShape.SetShape(tessellatedShape); //update the value in trace, since we had to modify the geometry we need a new syncId var updatedTraceData = new DirectShapeState(this, Guid.NewGuid().ToString(), materialId); ElementBinder.SetRawDataForTrace(updatedTraceData); //place new values in the tags dict if (shapeReference.Tags.LookupTag(this.InternalElementId.ToString()) == null) { shapeReference.Tags.AddTag(this.InternalElementId.ToString(), updatedTraceData); } else { var storedState = shapeReference.Tags.LookupTag(this.InternalElementId.ToString()) as DirectShapeState; storedState.syncId = updatedTraceData.syncId; storedState.materialId = updatedTraceData.materialId; storedState.IntID = updatedTraceData.IntID; storedState.StringID = updatedTraceData.StringID; } TransactionManager.Instance.TransactionTaskDone(); }
public void RawTraceInteractionTestWithMultipleIDs() { var elementIDs = new MultipleSerializableId { IntIDs = { 42, 20 }, StringIDs = { "{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}", "{A79294BF-6D27-4B86-BEE9-D6921C11D495}" } }; //Raw write ElementBinder.SetRawDataForTrace(elementIDs); elementIDs = null; //Readback var readback = (MultipleSerializableId)ElementBinder.GetRawDataFromTrace(); //Verify that the data is correct Assert.IsTrue(readback.IntIDs.Count == 2); Assert.IsTrue(readback.IntIDs[0] == 42); Assert.IsTrue(readback.IntIDs[1] == 20); Assert.IsTrue(readback.StringIDs.Count == 2); Assert.IsTrue(readback.StringIDs[0].Equals("{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}")); Assert.IsTrue(readback.StringIDs[1].Equals("{A79294BF-6D27-4B86-BEE9-D6921C11D495}")); }
/// <summary> /// Initialize a Level element /// </summary> /// <param name="elevation"></param> /// <param name="name"></param> private void InitLevel(double elevation, string name) { //Phase 1 - Check to see if the object exists and should be rebound var oldEle = ElementBinder.GetElementAndTraceData <Autodesk.Revit.DB.Level, LevelTraceData>(Document); //There was an element, bind & mutate if (oldEle != null) { InternalSetLevel(oldEle.Item1); InternalSetElevation(elevation); InternalSetName(oldEle.Item2.InputName, name); return; } //There was no element, create a new one TransactionManager.Instance.EnsureInTransaction(Document); Autodesk.Revit.DB.Level level; if (Document.IsFamilyDocument) { level = Autodesk.Revit.DB.Level.Create(Document, elevation); } else { level = Autodesk.Revit.DB.Level.Create(Document, elevation); } InternalSetLevel(level); InternalSetName(string.Empty, name); var traceData = new LevelTraceData(this, name); TransactionManager.Instance.TransactionTaskDone(); ElementBinder.SetRawDataForTrace(traceData); }
public void TwoInstancesOfSerializableIdAreEqual() { var elementID = new SerializableId { IntID = 42, StringID = "{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}" }; var elementID2 = new SerializableId { IntID = 42, StringID = "{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}" }; //Raw write ElementBinder.SetRawDataForTrace(elementID); elementID = null; //Readback var readback = (SerializableId)ElementBinder.GetRawDataFromTrace(); //verify that the id extracted from trace is equal to the new instance Assert.IsTrue(readback.Equals(elementID2)); }
public void TwoInstancesOfMultSerializableIdAreEqual() { var elementIDs = new MultipleSerializableId { IntIDs = { 42, 20 }, StringIDs = { "{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}", "{A79294BF-6D27-4B86-BEE9-D6921C11D495}" } }; var elementIDs2 = new MultipleSerializableId { IntIDs = { 42, 20 }, StringIDs = { "{BE507CAC-7F23-43D6-A2B4-13F6AF09046F}", "{A79294BF-6D27-4B86-BEE9-D6921C11D495}" } }; //Raw write ElementBinder.SetRawDataForTrace(elementIDs); elementIDs = null; //Readback var readback = (MultipleSerializableId)ElementBinder.GetRawDataFromTrace(); //verify that the id extracted from trace is equal to the new instance Assert.IsTrue(readback.Equals(elementIDs2)); }