Here is what the folks at caad.arch.rwth-aachen.de got when they combined context aware panels (http://buildz.blogspot.de/2013/01/ori…) and a bit of math (http://au.autodesk.com/?nd=class&…) and documented it with Image-O-Matic
Month: February 2013
Move improvements to the Keyboard Shortcut Tutor
Another set of improvements have been made to the Keyboard Shortcut Tutor. It now:
- Works with ribbon buttons that contain drop-down lists such as Wall and Roof
- Works with sketch commands (Line, Rectangle, Circle, etc.)
- Shows the shortcut reminder immediately after most commands are invoked
- Gives focus to the Revit window after showing the reminder
You can download this version at https://boostyourbim.wordpress.com/products/#KeyboardTutor
‘Family Security Guard’ app now available for download
The user will be prompted for a password in two situations:
You can control if you want this check enabled for all Revit family files or not as follows:
After the password is successfully entered, the user will not be prompted again for the password during that Revit session. If you purchase a license, a custom password can be set in the pwd.txt file in the BoostYourBIM-FamilySecurity.bundle\Contents folder. NOTE: This app only protects families when this app is installed. There is no protection when someone without this app attempts to modify families. |
Deadline extended for the Image-O-Matic contest
This little bird told me that there are some crazy awesome things being done out there in the BIM-o-sphere with Revit and Image-O-Matic.
So I’m extending the deadline for the custom-built Revit API app until March 15. I look forward to seeing what you’re up to!
‘Move Physical to Analytical’ app now available
Here’s something especially for all you Revit Structure fans…
This free app is now available at the Autodesk App Store at http://apps.exchange.autodesk.com/RVT/Detail/Index?id=appstore.exchange.autodesk.com%3amovetoanalytical%3aen Here’s how it works
|
|
Keyboard Shortcut Tutor improved – new install available
I have made some improvements to the Keyboard Shortcut Tutor that you can download here:
The major change is that the reminder dialog is now shown after the command is complete instead of immediately after the ribbon button is pushed. This was needed to avoid a conflict with commands like Create Group and New Sheet that present a modal dialog box. For example, if you invoke the Wall tool from the ribbon, the reminder will now be shown after you finish creating walls.
Also fixed is the dialog background color is now always white but in the previous version appeared as black with certain Windows display settings. This made the black text in the dialog unreadable.
Q) When is 1 divided by 3 = 0?
A) When you are doing integer division in C#.
Dividing two integers always produces an integer. That is why 1/3 = 0. You can either cast the integers into doubles (in the number2 example) or use doubles instead of integers (number3 example).
double number = 1 / 3;
double number2 = (double)1 / (double)3;
double number3 = 1.0 / 3.0;
TaskDialog.Show("Division","Your results are:\n" + number + "\n" + number2 + " \n" + number3);
Download the Revit Keyboard Shortcut Tutor today!
Keyboard Shortcut Tutor
Boost Your BIM’s keyboard shortcut tutor gives you a friendly reminder in a small modeless dialog box when you use the mouse to click on a command that has a keyboard shortcut. A button in the dialog lists all shortcuts. Free version provides reminders for shortcuts that contain the letter “W”. If you find it helpful and want reminders for all shortcuts, please purchase a license. |
Finding Text Size as a Built-In Parameter
The TextNoteType class is where a property to find the size of a Text type would ideally be found. But it is not.
However, all hope is not lost.
It is important to remember (and sometimes easy to forget), that there is also a huge set of parameters in the Revit API known as Built In Parameters. Many of these parameters work in the internal Revit code and not in the API, but many (such as TEXT_SIZE) are also perfectly usable in the API.
Usage:
TextNote textNote = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element).ElementId) as TextNote;
TextNoteType textNoteType = doc.GetElement(textNote.GetTypeId()) as TextNoteType;
Parameter textSizeParam = textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE);
TaskDialog.Show("Text Size", textSizeParam.AsDouble().ToString());
What views use which view templates? (2013 edition and better formatting)
View Templates got a big makeover in Revit 2013, so the previous post needs to be modified slightly to run in Revit 2013. I’ve also improved the format of the output so it looks like this:
---------------- Summary --------------------------- Architectural Elevation: 4 Architectural Plan: 2 Architectural Reflected Ceiling Plan: 2 Site Plan: 1 Structural Framing Plan: 0 Structural Framing Elevation: 0 Architectural Section: 0 Site Section: 0 Structural Section: 0 Architectural Presentation 3D: 0 Architectural Presentation Elevation: 0 Export to Civil Engineering: 0 ---------------- Details --------------------------- 'Architectural Elevation' is View Template for 4 views Elevation East Elevation North Elevation West Elevation South 'Architectural Plan' is View Template for 2 views FloorPlan Level 1 FloorPlan Level 2 'Architectural Reflected Ceiling Plan' is View Template for 2 views CeilingPlan Level 1 CeilingPlan Level 2 'Site Plan' is View Template for 1 views FloorPlan Site 'Structural Framing Plan' is View Template for 0 views 'Structural Framing Elevation' is View Template for 0 views 'Architectural Section' is View Template for 0 views 'Site Section' is View Template for 0 views 'Structural Section' is View Template for 0 views 'Architectural Presentation 3D' is View Template for 0 views 'Architectural Presentation Elevation' is View Template for 0 views 'Export to Civil Engineering' is View Template for 0 views
The view parameter “Default View Template” has been renamed “View Template” and the API has a new property View.ViewTemplateId. 2013 also obsoleted Document.get_Element, replacing it with Document.GetElement.
public void TemplateUse()
{
Document doc = this.ActiveUIDocument.Document;
Dictionary<string, IList<string>> dict = new Dictionary<string, IList<string>>();
foreach (View viewTemplate in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where v.IsTemplate select v))
{
IList<string> viewsUsed = new List<string>();
foreach (View view in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where !(v.IsTemplate) select v))
{
ElementId id = view.ViewTemplateId;
if (id != ElementId.InvalidElementId)
{
Element e = doc.GetElement(id);
if (e.Name == viewTemplate.Name)
viewsUsed.Add(view.ViewType.ToString() + " " + view.Name);
}
}
dict.Add(viewTemplate.Name, viewsUsed);
}
// sort the dictionary based on the number of views in each list
var items = from pair in dict orderby pair.Value.Count descending select pair;
string filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ViewTemplateUsage.txt");
using (StreamWriter sr = new StreamWriter(filename, false))
{
sr.WriteLine("---------------- Summary ---------------------------");
foreach (KeyValuePair<string, IList<string>> pair in items)
{
sr.WriteLine(pair.Key + ": " + pair.Value.Count);
}
sr.WriteLine();
sr.WriteLine("---------------- Details ---------------------------");
foreach (KeyValuePair<string, IList<string>> pair in items)
{
sr.WriteLine("'" + pair.Key + "' is View Template for " + pair.Value.Count + " views");
foreach (string name in pair.Value)
{
sr.WriteLine(name);
}
sr.WriteLine();
}
}
Process.Start(filename);
}
What views use which view templates? (2012 edition)
Steve wrote at Revit OpEd:
When I travel back and forth between Revit versions, say between 12 and 13, I find myself missing things. For example I wanted to see (in 2012) how many views were assigned to view templates and which ones were really being used. In 2013 we can add that parameter to a View List, 2012 not so much. In 2013 we can select a view template and see how many views are assigned to it, in 2012…you get the idea. I wish life and project conditions didn’t make it hard to “just upgrade”. Just do it, as soon as you can!
Sometimes when you can’t upgrade your RVT to a newer version of Revit, you can use the Revit API to accomplish something similar (or even better!) than what you would do in the newer release of Revit. Here is a Revit 2012 macro that outputs a text file listing all view templates with the count and names of the views that use it as the default view template:
'Architectural Elevation' is Default View Template for 4 views Elevation East, Elevation North, Elevation West, Elevation South, 'Architectural Plan' is Default View Template for 2 views FloorPlan Level 1, FloorPlan Level 2, 'Architectural Reflected Ceiling Plan' is Default View Template for 2 views CeilingPlan Level 1, CeilingPlan Level 2, 'Site Plan' is Default View Template for 1 views FloorPlan Site, 'Structural Framing Plan' is Default View Template for 0 views 'Structural Framing Elevation' is Default View Template for 0 views 'Architectural Section' is Default View Template for 0 views 'Site Section' is Default View Template for 0 views 'Structural Section' is Default View Template for 0 views 'Architectural Presentation 3D' is Default View Template for 0 views 'Architectural Presentation Elevation' is Default View Template for 0 views 'Export to Civil Engineering' is Default View Template for 0 views
public void TemplateUse()
{
Document doc = this.ActiveUIDocument.Document;
Dictionary<string, IList<string>> dict = new Dictionary<string, IList<string>>();
foreach (View viewTemplate in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where v.IsTemplate select v))
{
IList<string> viewsUsed = new List<string>();
foreach (View view in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where !(v.IsTemplate) select v))
{
Parameter p = view.get_Parameter("Default View Template");
if (p != null)
{
ElementId id = p.AsElementId();
if (id != ElementId.InvalidElementId)
{
Element e = doc.get_Element(p.AsElementId());
if (e.Name == viewTemplate.Name)
viewsUsed.Add(view.ViewType.ToString() + " " + view.Name);
}
}
}
dict.Add(viewTemplate.Name, viewsUsed);
}
// sort the dictionary based on the number of views in each list
var items = from pair in dict orderby pair.Value.Count descending select pair;
string filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ViewTemplateUsage.txt");
using (StreamWriter sr = new StreamWriter(filename, false))
{
foreach (KeyValuePair<string, IList<string>> pair in items)
{
sr.WriteLine("'" + pair.Key + "' is Default View Template for " + pair.Value.Count + " views");
string s = "";
foreach (string name in pair.Value)
{
s += name + ", ";
}
sr.WriteLine(s);
sr.WriteLine();
}
}
Process.Start(filename);
}
Download links for the RevitAPI help files
- 2012 RevitAPI.chm
- 2013 RevitAPI.chm
- 2014 RevitAPI.chm
- 2015 RevitAPI.chm
- 2016 RevitAPI.chm
- 2017 RevitAPI.chm
After downloading these files, go to the File Properties dialog and click “Unblock” to allow them to display their contents.
How to use Boost Your BIM source code to create working macros
A video showing the complete process of using use the code from these posts to create and compile a working macro.
https://boostyourbim.wordpress.com/2013/02/10/macro-to-quickly-fix-the-tofrom-room-parameter-for-doors/
https://boostyourbim.wordpress.com/2012/12/23/using-statements/
Set adaptive component parameters with placement point coordinates
A reader asked how to compute and schedule the placement point coordinates of adaptive component families. Here is a sample using the Parameter API and Dynamic Model Update to get and set those values.
private void Module_Startup(object sender, EventArgs e)
{
AdaptivePointParamUpdater updater = new AdaptivePointParamUpdater(this.Application.ActiveAddInId);
try
{
UpdaterRegistry.RegisterUpdater(updater);
UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), new ElementClassFilter(typeof(FamilyInstance)), Element.GetChangeTypeElementAddition());
UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), new ElementClassFilter(typeof(FamilyInstance)), Element.GetChangeTypeGeometry());
}
catch{}
}
public class AdaptivePointParamUpdater : IUpdater
{
static AddInId m_appId;
static UpdaterId m_updaterId;
public AdaptivePointParamUpdater(AddInId id)
{
m_appId = id;
m_updaterId = new UpdaterId(m_appId, new Guid("1BF1F6A2-4C06-42d4-97C1-D1B4EB593EFF"));
}
public void Execute(UpdaterData data)
{
Document doc = data.GetDocument();
Autodesk.Revit.ApplicationServices.Application app = doc.Application;
foreach (ElementId id in data.GetAddedElementIds())
{
adaptivePointParams(data.GetDocument(), id);
}
foreach (ElementId id in data.GetModifiedElementIds())
{
adaptivePointParams(data.GetDocument(), id);
}
}
public string GetAdditionalInformation(){return "Data about adaptive parameters";}
public ChangePriority GetChangePriority(){return ChangePriority.FloorsRoofsStructuralWalls;}
public UpdaterId GetUpdaterId(){return m_updaterId;}
public string GetUpdaterName(){return "AdaptivePoints";}
private void adaptivePointParams(Document doc, ElementId id)
{
FamilyInstance fi = doc.GetElement(id) as FamilyInstance;
if (fi != null && AdaptiveComponentInstanceUtils.IsAdaptiveComponentInstance(fi))
{
int ctr = 1;
foreach (ElementId elementId in AdaptiveComponentInstanceUtils.GetInstancePlacementPointElementRefIds(fi))
{
ReferencePoint rp = doc.GetElement(elementId) as ReferencePoint;
XYZ position = rp.Position;
if (ctr == 1)
{
fi.get_Parameter("point1x").Set(Math.Round(position.X,3));
fi.get_Parameter("point1y").Set(Math.Round(position.Y,3));
fi.get_Parameter("point1z").Set(Math.Round(position.Z,3));
}
else if (ctr == 2)
{
fi.get_Parameter("point2x").Set(Math.Round(position.X,3));
fi.get_Parameter("point2y").Set(Math.Round(position.Y,3));
fi.get_Parameter("point2z").Set(Math.Round(position.Z,3));
}
ctr++;
}
}
}
}
Thanks Marco for using Image-O-Matic
What have you been doing with Image-O-Matic? Care to share for the chance to win a custom designed Revit API application?
Macro to quickly fix the To/From Room parameter for doors
Steve, the wizard of revitoped.blogspot.com, suggested:
It would be cool to use the API to allow a user to pick a door and room to resolve the to/from settings. A user was lamenting the labor hassle of fixing to/from settings because people are mirroring and copying doors which doesn’t necessarily inherit the correct room ownership.
This macro works as follows
- Select a door or door tag
- Select the To Room (either the Room or the Room Tag)
- Repeat as desired, press the ESC key when done
public void FlipRoom()
{
UIDocument uidoc = this.ActiveUIDocument;
Document doc = uidoc.Document;
FamilyInstance door = null;
string doorMark = "";
while (true) // create an infinite loop that will be ended by the "return" statement in the catch block
{
try
{
Element element = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select a door or door tag"));
if (element is FamilyInstance) // if door is selected
door = element as FamilyInstance;
else if (element is IndependentTag) // if door tag is selected
{
IndependentTag tag = element as IndependentTag;
door = doc.GetElement(tag.TaggedLocalElementId) as FamilyInstance;
}
doorMark = door.get_Parameter("Mark").AsString();
}
catch
{
return; // end the command when the user presses ESC when prompted for a door
}
// after the user has selected a door, prompt for selection of a room
Element e = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select To Room for door " + doorMark));
// Get the room element from the selected object
Room room = null;
if (e is RoomTag)
{
RoomTag rt = e as RoomTag;
room = rt.Room;
}
else if (e is Room)
{
room = e as Room;
}
if (room != null && door.ToRoom.Id.IntegerValue != room.Id.IntegerValue) // if the selected room is not already the To Room
{
using (Transaction t = new Transaction(doc,"Door " + doorMark + " to room = " + room.Number))
{
t.Start();
door.FlipFromToRoom(); // Flip the settings of "From Room" and "To Room" for the door
t.Commit();
}
}
}
}
Setting door position relative to nearby walls
A reader sent the image on the right and asked: “can we make door with specific distance to face of wall like 20 cm without every time need to adjust distance in temporary dimension ?”
This seemed like a good excuse to stop writing code dealing with Family Parameters (I was getting tired of writing it, were you getting tired of reading about it?).
|
Bulk Family Parameter Editing Improvements
Thanks to everyone for their enthusiasm and feedback on my recent posts about exporting family parameters to Excel and modifying the parameter data.
I’ve added the Shared Parameter GUIDs, the ability to modify parameters stored as text, integer, and double values, and UI for specifying folders and files. Are there other changes that would be valuable to make before I publish the tool?
API code for all languages (when possible) with TaskDialog Ids and WriteJournalComment
Arnost makes a good comment below reminding us to think about how Revit and our API applications will work with non-English versions of Revit.
Please remember that the text will not always be in English! It comes from resources and will be properly localized in foreign versions of Revit. Using the string locally is all right, but it is better to rely on Dialog Id, which should also be available (although not always is) in the event argument.
He was writing in response to the code I posted:
t.Message == "The floor/roof overlaps the highlighted wall(s). Would you like to join geometry and cut the overlapping volume out of the wall(s)?"
It would be better to avoid including the English text in the API logic, but sometimes we have no choice. Here are 5 task dialogs – 2 have a DialogId and for 3 that property is empty. And when there is no DialogId the only option is to base the comparison on the text string of the message.
‘C 02-Feb-2013 14:16:39.716; 1:< TaskDialogShowingEventArgs,The floor/roof overlaps the highlighted wall(s). Would you like to join geometry and cut the overlapping volume out of the wall(s)?,,
‘C 02-Feb-2013 14:16:21.362; 1:< TaskDialogShowingEventArgs,Would you like to attach the highlighted walls to the roof?,,
‘C 02-Feb-2013 14:15:41.234; 1:< TaskDialogShowingEventArgs,Would you like to rename corresponding views?,,
‘C 02-Feb-2013 14:21:03.890; 2:< TaskDialogShowingEventArgs,Do you want to save changes to uni2.rvt?,TaskDialog_Save_File,
‘C 02-Feb-2013 14:22:10.362; 1:< TaskDialogShowingEventArgs,You are trying to load the family Table-Dining Round w Chairs, which already exists in this project. What do you want to do?,TaskDialog_Family_Already_Exists,
Here’s the macro code to write the TaskDialog message text and id to the journal file.
private void Module_Startup(object sender, EventArgs e)
{
UIApplication uiapp = new UIApplication(this.Application);
uiapp.DialogBoxShowing += new EventHandler<DialogBoxShowingEventArgs>(taskDialogInfo);
}
private void taskDialogInfo(object o, DialogBoxShowingEventArgs e)
{
TaskDialogShowingEventArgs t = e as TaskDialogShowingEventArgs;
if (t != null)
this.Application.WriteJournalComment("TaskDialogShowingEventArgs," + t.Message + "," + t.DialogId + ",",true);
}
In most cases it can be more convenient to show the data (t.Message and t.DialogId)
in a TaskDialog, but you can’t show a TaskDialog during the DialogBoxShowing event when Revit is trying to show its own dialog box.
Using “Step Into” to look at the values in Sharp Develop usually works, but you can’t step into a function that is triggered when an event occurs.
So WriteJournalComment is a great solution in this case.
How to Automatically Dismiss a Revit dialog
For my friend who asked:
Is it possible to disable the pop-up, when you edit a floor: -Would you like walls that go up to his floor’s level to attach to its bottom?- I never want to do this, it’s annoying
Here is how to automatically dismiss that or any other Message Box or Task Dialog
private void Module_Startup(object sender, EventArgs e)
{
UIApplication uiapp = new UIApplication(this.Application);
// Subscribe to the DialogBoxShowing event to be notified when Revit is about to show a dialog box or a message box.
uiapp.DialogBoxShowing += new EventHandler(dismissFloorQuestion);
}
private void dismissFloorQuestion(object o, DialogBoxShowingEventArgs e)
{
// DialogBoxShowingEventArgs has two subclasses - TaskDialogShowingEventArgs & MessageBoxShowingEventArgs
// In this case we are interested in this event if it is TaskDialog being shown.
TaskDialogShowingEventArgs t = e as TaskDialogShowingEventArgs;
if (t != null && t.Message == "The floor/roof overlaps the highlighted wall(s). Would you like to join geometry and cut the overlapping volume out of the wall(s)?")
{
// Call OverrideResult to cause the dialog to be dismissed with the specified return value
// (int) is used to convert the enum TaskDialogResult.No to its integer value which is the data type required by OverrideResult
e.OverrideResult((int)TaskDialogResult.No);
}
}
Remember to add this line to the top of the file to avoid compilation errors:
using Autodesk.Revit.UI.Events;