What is the purpose of this function? I understand that it allows us to create transient elements that does not belong to the document. I was thinking it could be used to make jig/preview like in AutoCAD but the elements created does not seems to appear on the screen.
Solved! Go to Solution.
Solved by jeremytammik. Go to Solution.
Dear Maxence,
Thank you for your query.
I am checking with the development team for you.
Best regards,
Jeremy
Interesting...
"Transient elements are usually created for short term use. This type of element can be created via Document.MakeTransientElements().
Transient and Permanent elements are not allowed to reference each other. A transient element can only refer to other transient elements in the same document.
Transient elements also cannot be selected or scheduled, and will not be saved when the document is saved, and will be discarded when the document is closed.
Modifying a transient element does not require a transaction, because such elements are not part of the model. As an effect of this, however, creation and modification of transients cannot be undone.
Because transient elements are technically not part of the model, they will not be found when using standard element filters, or in any collection of elements Revit returns, such as elements reported in dynamic updaters, etc."
Very Dynamo.
Below only appeared when I moved the view cube, call to RefreshActiveView in code below didn't help show it either.
Unclear if this is DirectShapes only.
Public Class MyFirstTransientObject Implements ITransientElementMaker Private IntTDoc As Document = Nothing Public Sub New(D As Document) IntTDoc = D End Sub Public Sub Execute() Implements ITransientElementMaker.Execute Dim CLx As New List(Of Curve) CLx.Add(Line.CreateBound(New XYZ(0, 0, 0), New XYZ(5, 0, 0))) CLx.Add(Line.CreateBound(New XYZ(5, 0, 0), New XYZ(5, 5, 0))) CLx.Add(Line.CreateBound(New XYZ(5, 5, 0), New XYZ(0, 5, 0))) CLx.Add(Line.CreateBound(New XYZ(0, 5, 0), New XYZ(0, 0, 0))) Dim CL As CurveLoop = CurveLoop.Create(CLx) Dim CL_Set As New List(Of CurveLoop) CL_Set.Add(CL) Dim S As Solid = GeometryCreationUtilities.CreateExtrusionGeometry(CL_Set, XYZ.BasisZ, 10) Dim DS As DirectShape = DirectShape.CreateElement(IntTDoc, New ElementId(BuiltInCategory.OST_GenericModel)) Dim GeomList As New List(Of GeometryObject) GeomList.Add(S) DS.AppendShape(GeomList) End Sub End Class Private Function TObj(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData, _ ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result If commandData.Application.ActiveUIDocument Is Nothing Then Return Result.Failed Else Dim IntDoc As Document = commandData.Application.ActiveUIDocument.Document IntDoc.MakeTransientElements(New MyFirstTransientObject(IntDoc)) commandData.Application.ActiveUIDocument.RefreshActiveView() End Function
Hello @jeremytammik was there any response to this initial enquiry above.
These objects have been around for a while now it seems but there are no real examples of their usage. I imagine they will be useful for indicating things in a temporary way such as room numbers, grids or perhaps indicating clashes etc.
A couple of things I'm unsure about:
Are we meant to be using them? They don't appear unless you move the ViewCube.
How do we manage their lifecycle? We can create them but their duration seems random. Is there a way we can maintain them on screen for longer or call their destruction earlier?
Are they for DirectShape objects only?
Dear Richard,
Thank you very much for the nice sample, your research, and the reminder.
I re-prompted the development team for a response and added your detailed questions to that.
Cheers,
Jeremy
Dear All,
The question is finally resolved, and unfortunately the answer is not very exciting, nor very unexpected:
This seems to be 'half-finished' work that should not have been exposed to public API.
It looks like it never worked reliably and will probably be removed again.
So, the short answer to users: please do not use it.
I hope this clarifies.
Cheers,
Jeremy
Thanks Jeremy,
That is a bit of a shame given the possibilities. They wrote so much about it in the chm and created an IsTransient property on Element.
Oh well.
Regards
Richard
Just came a cross this in 2021 tried on Revit 2022 and still there. does this means the Work is completed? is there any possible example to get a quick idea how this will work?
Dear Mostafa,
You are able to answer this (and many other similar questions as well) by taking a quick look at What's New in the Revit 2022 API and searching for MakeTransientElements:
https://thebuildingcoder.typepad.com/blog/2021/04/whats-new-in-the-revit-2022-api.html
Unfortunately, I find no mention of it, so I assume the situation is unchanged.
Cheers,
Jeremy
I never looked into it any further didn't see the point of making use of something that was noted as going to be removed (a true transient feature).
From testing at the time it seemed to work reasonably well but there was no clear context for it so lifecycle of objects was unpredictable in code. Probably removing the graphics was what was missing.
You have DirectContext3D as an alternative approach to this kind of functionality. Can create solids (or extract from geometry) then extract face triangles/edges from those solids and feed into this server.
Thanks @RPTHOMAS108 @jeremy_tammik I did and still using the Direct3dContext. I was just wondering if there is any documented updated towards the Transient .
After a couple of search I found this:
Using the interface "ITransientElementMaker" didn't show any thing on the GraphicalView, I tried refreshing the view and still nothing.
internal class TransientMaker : ITransientElementMaker
{
public void Execute()
{
DirectShape directShape = DirectShape.CreateElement(m_doc, new ElementId(BuiltInCategory.OST_GenericModel));
directShape.AppendShape(new List<GeometryObject>() { CreateCube() });
}
public Solid CreateCube()
{
CurveLoop cubeBaseLines = new CurveLoop();
cubeBaseLines.Append(Line.CreateBound(new XYZ(0, 0, 0), new XYZ(100, 0, 0)));
cubeBaseLines.Append(Line.CreateBound(new XYZ(100, 0, 0), new XYZ(100, 100, 0)));
cubeBaseLines.Append(Line.CreateBound(new XYZ(100, 100, 0), new XYZ(0, 100, 0)));
cubeBaseLines.Append(Line.CreateBound(new XYZ(0, 100, 0), new XYZ(0, 0, 0)));
var solidCube = GeometryCreationUtilities.CreateExtrusionGeometry(new List<CurveLoop> { cubeBaseLines }, XYZ.BasisZ, 100);
return solidCube;
}
}
and the above is called from the ExternalCommand:
var trans = new TransientMaker();
m_doc.MakeTransientElements(trans);
** it doesn't Require any transaction to work else exception will throw.
After a couple of searches I found ZiyunShang did it using a hacky way. Basically, he executed the method "SetForTransientDisplay" using Reflection, inspired from Dynamo. This will make a Geometry Transient.
Coded like this:
using (Transaction t = new Transaction(m_doc, "Create Transient"))
{
t.Start();
IEnumerable<GeometryObject> geoms = new List<GeometryObject>() { CreateCube() };
var method = GenerateTransientDisplayMethod();
var argsM = new object[4];
argsM[0] = m_doc;
argsM[1] = ElementId.InvalidElementId;
argsM[2] = geoms;
argsM[3] = ElementId.InvalidElementId;
var transientId= (ElementId)method.Invoke(null, argsM); t.Commit();
}
internal static MethodInfo GetTransientDisplayMethod()
{
var geometryElementType = typeof(GeometryElement);
var geometryElementTypeMethods =
geometryElementType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var method = geometryElementTypeMethods.FirstOrDefault(x => x.Name == "SetForTransientDisplay");
return method;
}
and To delete "eliminate" the Created Transient, we use the normal Deletion method.
using (Transaction t = new Transaction(m_doc, "Delete Transient"))
{
t.Start();
m_doc.Delete(transientId);
t.Commit();
}
The thing that drives a question, why a document.Delete(eId) is required to delete an object that originally doesn't exist in the projectdocument, even the projectdocument it self doesn't consider it self changed. Meaning the moment you close the opened Project, it doesn't ask for a save. which is also contrary to the commited transaction used to generate the transient.
This is all i got since yesterday's discussion. I will try to dig deeper later if necessary.
Credit goes to ZiyunShang
Additional things I noticed while exploring the Source code.
@Moustafa_K I don't think you do actually need a transaction to show it. From reading what I originally wrote I recall that nothing showed until I moved the view cube slightly i.e. the code I left above was able to show the transient object fine. However there was nothing likewise to hide it. Would have expected Document.MakeTransientElements to be a function returning an object that could be disposed of or for there to be another Document method to remove such an object.
Interesting that a call to delete removes it, as you say it makes no real sense to delete something that was never added to the database. Personally I'd just not invest any future reliance on the feature at this point.
Hi @Moustafa_K,
I saw this very interesting topic. I also was looking for a method to do this only with a simple arc line.
Would this also be possible? i tried to implement your code but got a lot of errors also with the m_doc
Maybe you have a Solution file to see how you can implement this right in visual studio?
Thanks.
With kind regards,
Folkert