diff --git a/dev/WPFEdit/WPFEdit/WPFEdit.csproj b/dev/WPFEdit/WPFEdit/WPFEdit.csproj
index fc03bc2f7..33a40d970 100644
--- a/dev/WPFEdit/WPFEdit/WPFEdit.csproj
+++ b/dev/WPFEdit/WPFEdit/WPFEdit.csproj
@@ -105,6 +105,11 @@
MSBuild:Compile
Designer
+
+ Tools\MatchConfigWindowLegacy.xaml
+ MSBuild:Compile
+ Designer
+
Tools\MakePatternWindow.xaml
MSBuild:Compile
diff --git a/dev/todo.todo b/dev/todo.todo
index b34411f7f..f5e7b4b2d 100644
--- a/dev/todo.todo
+++ b/dev/todo.todo
@@ -3,5 +3,8 @@ pyrevit cli:
installer:
pyrevit:
+ ☐ fix log messages in tools
+ ☐ faster sheet titleblock selection tool
+ ☐ the help uri for splitpushbutton doesn't work correctly e.g match tool
☐ slowly move collectors in List tool to db.query
☐ slowly phase out the extpackages module and user PyRevitLabs
diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/_layout b/extensions/pyRevitCore.extension/pyRevit.tab/_layout
new file mode 100644
index 000000000..301808084
--- /dev/null
+++ b/extensions/pyRevitCore.extension/pyRevit.tab/_layout
@@ -0,0 +1 @@
+pyRevit[beforeall:]
\ No newline at end of file
diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml
index ca2024444..8ef887247 100644
--- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml
+++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml
@@ -80,7 +80,7 @@
- Rocket Mode 🚀 (Experimental / Reload Required)
+ Rocket Mode 🚀 (Reload Required)
This is the switch for pyRevit Rocket Mode.
If enabled, pyRevit will use a shared engine per each extension
diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/tools.stack3/Spy.pulldown/Get Central Path.pushbutton/script.py b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/tools.stack3/Spy.pulldown/Get Central Path.pushbutton/script.py
index b83a4cc69..2bffc077c 100644
--- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/tools.stack3/Spy.pulldown/Get Central Path.pushbutton/script.py
+++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/tools.stack3/Spy.pulldown/Get Central Path.pushbutton/script.py
@@ -1,12 +1,8 @@
-__doc__ = 'Print the full path to the central model (if model is workshared).'
+"""Print the full path to the central model (if model is workshared)."""
-
-from pyrevit import revit, DB, UI
+#pylint: disable=E0401
+from pyrevit import revit
from pyrevit import forms
-if revit.doc.IsWorkshared:
- model_path = revit.doc.GetWorksharingCentralModelPath()
- print(DB.ModelPathUtils.ConvertModelPathToUserVisiblePath(model_path))
-else:
- forms.alert('Model is not workshared.')
+forms.check_workshared(doc=revit.doc)
diff --git a/extensions/pyRevitTools.extension/extension.json b/extensions/pyRevitTools.extension/extension.json
index 0b6878dac..7e81c3255 100644
--- a/extensions/pyRevitTools.extension/extension.json
+++ b/extensions/pyRevitTools.extension/extension.json
@@ -10,5 +10,9 @@
"url": "https://github.com/eirannejad/pyRevit.git",
"website": "http://eirannejad.github.io/pyRevit/",
"image": "",
+ "templates": {
+ "author": "Ehsan Iran-Nejad",
+ "docpath": "https://www.youtube.com/watch?v="
+ },
"dependencies": []
}
\ No newline at end of file
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Linked Elements.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Linked Elements.pushbutton/script.py
index 0020ef1a0..0a93e4dee 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Linked Elements.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Inspect.pulldown/Find Linked Elements.pushbutton/script.py
@@ -3,7 +3,7 @@
__context__ = 'selection'
-__helpurl__ = 'https://www.youtube.com/watch?v=4IlvCkoOolw'
+__helpurl__ = '{{docpath}}4IlvCkoOolw'
__doc__ = 'Lists all the elements that are tied to the selected element.'\
' For example elements tags or dimensions.'
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Sum.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Sum.pushbutton/script.py
index 38eacca76..79f70b607 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Sum.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Analysis.panel/Tools.stack2/Sum.pushbutton/script.py
@@ -149,8 +149,9 @@ def process_sets(element_list):
el_sets[el.LineStyle.Name].append(el)
else:
eltype = revit.doc.GetElement(el.GetTypeId())
- wrapped_eltype = revit.ElementWrapper(eltype)
- el_sets[wrapped_eltype.name].append(el)
+ if eltype:
+ wrapped_eltype = revit.ElementWrapper(eltype)
+ el_sets[wrapped_eltype.name].append(el)
return el_sets
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Print.pulldown/Print Ordered Sheet Index.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Print.pulldown/Print Ordered Sheet Index.pushbutton/script.py
index 825bc0323..83a5bdbdc 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Print.pulldown/Print Ordered Sheet Index.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Print.pulldown/Print Ordered Sheet Index.pushbutton/script.py
@@ -97,6 +97,18 @@ def show_placeholders(self):
def include_placeholders(self):
return self.indexspace_cb.IsChecked
+ @property
+ def sheet_list(self):
+ return self.sheets_lb.ItemsSource
+
+ @sheet_list.setter
+ def sheet_list(self, value):
+ self.sheets_lb.ItemsSource = value
+
+ @property
+ def printable_sheets(self):
+ return [x for x in self.sheet_list if x.printable]
+
def _get_schedule_text_data(self, schedule_view):
schedule_data_file = \
script.get_instance_data_file(str(schedule_view.Id.IntegerValue))
@@ -112,8 +124,8 @@ def _get_schedule_text_data(self, schedule_view):
as sched_data_file:
return sched_data_file.readlines()
except Exception as open_err:
- logger.error('Error opening sheet index export: {} | {}'
- .format(schedule_data_file, open_err))
+ logger.error('Error opening sheet index export: %s | %s',
+ schedule_data_file, open_err)
return sched_data
def _order_sheets_by_schedule_data(self, schedule_view, sheet_list):
@@ -126,13 +138,12 @@ def _order_sheets_by_schedule_data(self, schedule_view, sheet_list):
for sheet in sheet_list:
for line_no, data_line in enumerate(sched_data):
try:
- if sheet.CanBePrinted:
- if sheet.SheetNumber in data_line:
- ordered_sheets_dict[line_no] = sheet
- break
- else:
- logger.warning('Sheet {} is not printable.'
- .format(sheet.SheetNumber))
+ if sheet.SheetNumber in data_line:
+ ordered_sheets_dict[line_no] = sheet
+ break
+ if not sheet.CanBePrinted:
+ logger.debug('Sheet %s is not printable.',
+ sheet.SheetNumber)
except Exception:
continue
@@ -166,7 +177,7 @@ def _get_printmanager(self):
except Exception as printerr:
logger.critical('Error getting printer manager from document. '
'Most probably there is not a printer defined '
- 'on your system. | {}'.format(printerr))
+ 'on your system. | %s', printerr)
return None
def _print_combined_sheets_in_order(self):
@@ -182,11 +193,13 @@ def _print_combined_sheets_in_order(self):
sheet_set = DB.ViewSet()
original_sheetnums = []
with revit.Transaction('Fix Sheet Numbers') as t:
- for idx, sheet in enumerate(self.sheets_lb.ItemsSource):
- sht = sheet.revit_sheet
- original_sheetnums.append(sht.SheetNumber)
- sht.SheetNumber = NPC * (idx + 1) + sht.SheetNumber
- sheet_set.Insert(sht)
+ for idx, sheet in enumerate(self.sheet_list):
+ rvtsheet = sheet.revit_sheet
+ original_sheetnums.append(rvtsheet.SheetNumber)
+ rvtsheet.SheetNumber = \
+ NPC * (idx + 1) + rvtsheet.SheetNumber
+ if sheet.printable:
+ sheet_set.Insert(rvtsheet)
# Collect existing sheet sets
cl = DB.FilteredElementCollector(revit.doc)
@@ -222,7 +235,7 @@ def _print_combined_sheets_in_order(self):
logger.critical(
'Error setting sheet set on print mechanism. '
'These items are included in the viewset '
- 'object:\n{}'.format(sheet_report)
+ 'object:\n%s', sheet_report
)
raise viewset_err
@@ -241,10 +254,10 @@ def _print_combined_sheets_in_order(self):
# now fix the sheet names
with revit.Transaction('Restore Sheet Numbers') as t:
- for sheet, sheetnum in zip(self.sheets_lb.ItemsSource,
+ for sheet, sheetnum in zip(self.sheet_list,
original_sheetnums):
- sht = sheet.revit_sheet
- sht.SheetNumber = sheetnum
+ rvtsheet = sheet.revit_sheet
+ rvtsheet.SheetNumber = sheetnum
def _print_sheets_in_order(self):
# make sure we can access the print config
@@ -254,7 +267,7 @@ def _print_sheets_in_order(self):
print_mgr.PrintToFile = True
# print_mgr.CombinedFile = False
print_mgr.PrintRange = DB.PrintRange.Current
- for sheet in self.sheets_lb.ItemsSource:
+ for sheet in self.sheet_list:
output_fname = \
coreutils.cleanup_filename('{:05} {} - {}.pdf'
.format(sheet.print_index,
@@ -265,8 +278,8 @@ def _print_sheets_in_order(self):
if sheet.printable:
print_mgr.SubmitPrint(sheet.revit_sheet)
else:
- logger.warning('Sheet {} is not printable. Skipping print.'
- .format(sheet.SheetNumber))
+ logger.debug('Sheet %s is not printable. Skipping print.',
+ sheet.number)
def _update_print_indices(self, sheet_list):
for idx, sheet in enumerate(sheet_list):
@@ -295,7 +308,7 @@ def selection_changed(self, sender, args):
if not self.include_placeholders:
self._update_print_indices(printable_sheets)
- self.sheets_lb.ItemsSource = printable_sheets
+ self.sheet_list = printable_sheets
else:
self.indexspace_cb.IsChecked = True
@@ -303,12 +316,12 @@ def selection_changed(self, sender, args):
# update print indices
self._update_print_indices(sheet_list)
# Show all sheets
- self.sheets_lb.ItemsSource = sheet_list
+ self.sheet_list = sheet_list
def print_sheets(self, sender, args):
- if self.sheets_lb.ItemsSource:
+ if self.sheet_list:
if not self.combine_print:
- sheet_count = len(self.sheets_lb.ItemsSource)
+ sheet_count = len(self.sheet_list)
if sheet_count > 5:
if not forms.alert('Are you sure you want to print {} '
'sheets individually? The process can '
@@ -340,7 +353,7 @@ def drop_sheet(self, sender, args):
dropped_idx = self.sheets_lb.Items.IndexOf(dropped_data)
target_idx = self.sheets_lb.Items.IndexOf(target)
- sheet_list = self.sheets_lb.ItemsSource
+ sheet_list = self.sheet_list
sheet_list.remove(dropped_data)
sheet_list.insert(target_idx, dropped_data)
self._update_print_indices(sheet_list)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Revision.pulldown/Create Revised Sheet Set.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Revision.pulldown/Create Revised Sheet Set.pushbutton/script.py
index c97064b9f..8f6135158 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Revision.pulldown/Create Revised Sheet Set.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Revision.pulldown/Create Revised Sheet Set.pushbutton/script.py
@@ -3,7 +3,6 @@
from pyrevit import forms
-__author__ = '{{author}}'
__doc__ = 'Select a revision from the list of revisions and this script '\
'will create a print sheet set for the revised sheets under the '\
'selected revision, and will assign the new sheet set as '\
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Batch Sheet Maker.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Batch Sheet Maker.pushbutton/script.py
index a29cbe751..3bf414145 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Batch Sheet Maker.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Batch Sheet Maker.pushbutton/script.py
@@ -6,7 +6,7 @@
from pyrevit import script
-__helpurl__ = "https://www.youtube.com/watch?v=SJzs9ZxqRYc"
+__helpurl__ = "{{docpath}}SJzs9ZxqRYc"
__doc__ = 'Enter sheet names and numbers in the text box and '\
'this tool will create all at once.'
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Copy Sheets to Open Documents.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Copy Sheets to Open Documents.pushbutton/script.py
index ecba88153..43f2bd103 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Copy Sheets to Open Documents.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/Sheets.pulldown/Copy Sheets to Open Documents.pushbutton/script.py
@@ -7,7 +7,7 @@
from Autodesk.Revit.DB import Element as DBElement
-__helpurl__ = 'https://www.youtube.com/watch?v=9Q-J6mWBYJI&t=17s'
+__helpurl__ = '{{docpath}}9Q-J6mWBYJI&t=17s'
__doc__ = 'Copies selected or current sheet(s) to other ' \
'projects currently open in Revit. Make sure the destination ' \
'documents have at least one Legend view (Revit API does not ' \
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends As Detail Views To Open Documents.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends As Detail Views To Open Documents.pushbutton/script.py
index 595804843..270f9387c 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends As Detail Views To Open Documents.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends As Detail Views To Open Documents.pushbutton/script.py
@@ -4,7 +4,7 @@
from pyrevit import forms
-__helpurl__ = 'https://www.youtube.com/watch?v=ThzcRM_Tj8g'
+__helpurl__ = '{{docpath}}ThzcRM_Tj8g'
__doc__ = 'Converts selected legend views to detail views and copies '\
'them to all projects currently open in Revit.'
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends To Open Documents.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends To Open Documents.pushbutton/script.py
index 8066953b9..ca36460c6 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends To Open Documents.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Legends.pulldown/Copy Selected Legends To Open Documents.pushbutton/script.py
@@ -6,7 +6,7 @@
from pyrevit import forms
-__helpurl__ = 'https://www.youtube.com/watch?v=ThzcRM_Tj8g'
+__helpurl__ = '{{docpath}}ThzcRM_Tj8g'
class CopyUseDestination(DB.IDuplicateTypeNamesHandler):
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Find Referring Views.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Find Referring Views.pushbutton/script.py
index cb4dff902..de6c4bb88 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Find Referring Views.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Find Referring Views.pushbutton/script.py
@@ -5,6 +5,7 @@
from pyrevit import script
+logger = script.get_logger()
output = script.get_output()
@@ -30,12 +31,12 @@
class ReferencingView:
def __init__(self, view_id):
- self.element = doc.GetElement(view_id)
+ self.element = revit.doc.GetElement(view_id)
if not self._valid_view():
raise Exception()
- title = self.element.LookupParameter('Title on Sheet').AsString()
- self.name = title if title else self.element.ViewName
+ titleos = self.element.LookupParameter('Title on Sheet').AsString()
+ self.name = titleos if titleos else self.element.ViewName
self.refs = []
self._update_refs(all_ref_els)
# self._update_refs(self.element.GetReferenceCallouts())
@@ -59,9 +60,12 @@ def _valid_view(self):
def _update_refs(self, el_list):
for elid in el_list:
- el = doc.GetElement(elid)
- if el.OwnerViewId == self.element.Id:
- self.refs.append(el.Name)
+ element = revit.doc.GetElement(elid)
+ viewnameparam = element.LookupParameter("View Name")
+ if element.OwnerViewId == self.element.Id \
+ or (viewnameparam \
+ and viewnameparam.AsString() == self.element.ViewName):
+ self.refs.append(element.Name)
def is_referring_to(self, view_name):
return view_name in self.refs
@@ -76,14 +80,13 @@ def is_sheeted(self):
try:
rv = ReferencingView(view.Id)
all_views.append(rv)
- except Exception:
- pass
+ except Exception as ex:
+ logger.debug(ex)
print('{} views processed...'.format(len(all_views)))
-for selid in selection:
- vp = revit.doc.GetElement(selid)
+for vp in selection:
if isinstance(vp, DB.Viewport):
v = revit.doc.GetElement(vp.ViewId)
title = v.LookupParameter('Title on Sheet').AsString()
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused Filters.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused Filters.pushbutton/script.py
index ac3bea39b..f0cc991c7 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused Filters.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused Filters.pushbutton/script.py
@@ -45,28 +45,28 @@ def name(self):
if not unusedFilters:
forms.alert('All filters are in use. No purging in necessary.')
-
-# ask user for wipe actions
-return_options = \
- forms.SelectFromList.show(
- [ViewFilterToPurge(revit.doc.GetElement(DB.ElementId(x)))
- for x in unusedFilters],
- title='Select Filters to Purge',
- width=500,
- button_name='Purge Filters',
- multiselect=True
- )
-
-# print('{} Filters have not been used and will be purged.'
-# .format(len(unusedFilters)))
-
-if return_options:
- with revit.Transaction('Purge Unused Filters'):
- for vf in return_options:
- logger.debug('Purging Filter: {0}\t{1}'
- .format(vf.Id, vf.Name))
- try:
- revit.doc.Delete(vf.Id)
- except Exception as del_err:
- logger.error('Error purging filter: {} | {}'
- .format(vf.Name, del_err))
+else:
+ # ask user for wipe actions
+ return_options = \
+ forms.SelectFromList.show(
+ [ViewFilterToPurge(revit.doc.GetElement(DB.ElementId(x)))
+ for x in unusedFilters],
+ title='Select Filters to Purge',
+ width=500,
+ button_name='Purge Filters',
+ multiselect=True
+ )
+
+ # print('{} Filters have not been used and will be purged.'
+ # .format(len(unusedFilters)))
+
+ if return_options:
+ with revit.Transaction('Purge Unused Filters'):
+ for vf in return_options:
+ logger.debug('Purging Filter: {0}\t{1}'
+ .format(vf.Id, vf.Name))
+ try:
+ revit.doc.Delete(vf.Id)
+ except Exception as del_err:
+ logger.error('Error purging filter: {} | {}'
+ .format(vf.Name, del_err))
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused View Templates.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused View Templates.pushbutton/script.py
index 26e79ab9c..32df3d89f 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused View Templates.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Purge Unused View Templates.pushbutton/script.py
@@ -35,7 +35,9 @@ def name(self):
unusedvtemp = vtemp - usedvtemp
-if unusedvtemp:
+if not unusedvtemp:
+ forms.alert('All View Templates are in use. No purging in necessary.')
+else:
# ask user for wipe actions
return_options = \
forms.SelectFromList.show(
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient Section Box To Face.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient Section Box To Face.pushbutton/script.py
index c3a2882f4..1087dc04e 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient Section Box To Face.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient Section Box To Face.pushbutton/script.py
@@ -5,7 +5,7 @@
from pyrevit import forms
-__helpurl__ = 'https://www.youtube.com/watch?v=b050tpp4vCE&t=42s'
+__helpurl__ = '{{docpath}}b050tpp4vCE&t=42s'
curview = revit.activeview
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient View To Face.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient View To Face.pushbutton/script.py
index 81e085083..c2b658e78 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient View To Face.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/3D.pulldown/Orient View To Face.pushbutton/script.py
@@ -3,7 +3,7 @@
from pyrevit import forms
-__helpurl__ = 'https://www.youtube.com/watch?v=pIjDd4dZng0'
+__helpurl__ = '{{docpath}}pIjDd4dZng0'
__doc__ = 'Reorients the current 3D view camera, perpendicular to the ' \
'selected face. This tool will set a sketch plane over the ' \
'selected face for 3d drawing.'
@@ -41,7 +41,7 @@ def reorient():
curview = revit.activeview
-if isinstance(curview, DB.View3D) and curview.IsSectionBoxActive:
+if isinstance(curview, DB.View3D):
reorient()
else:
forms.alert('You must be on a 3D view for this tool to work.')
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/MatchConfigWindow.xaml b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/MatchConfigWindow.xaml
index 39971e31c..2a83a695f 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/MatchConfigWindow.xaml
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/MatchConfigWindow.xaml
@@ -1,48 +1,86 @@
-
-
-
-
- Halftone
- Transparency
-
-
- Projection Line Color
- Projection Line Pattern
- Projection Line Weight
- Projection Fill Color
- Projection Fill Pattern
- Projection Fill Pattern Visibility
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Halftone
+ Transparency
+
+
+
+ Line Color
+ Line Pattern
+ Line Weight
+
+ Fill Color
+ Fill Pattern
+ Fill Pattern Visibility
+
+ Fill Color
+ Fill Pattern
+ Fill Pattern Visibility
-
-
- Cut Line Color
- Cut Line Pattern
- Cut Line Weight
- Cut Fill Color
- Cut Fill Pattern
- Cut Fill Pattern Visibility
+
+
+
+ Line Color
+ Line Pattern
+ Line Weight
+
+ Fill Color
+ Fill Pattern
+ Fill Pattern Visibility
+
+ Fill Color
+ Fill Pattern
+ Fill Pattern Visibility
-
-
-
-
- Replaced Value
- Text Position
- Above Value
- Below Value
- Prefix Value
- Postfix Value
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Prefix Value
+ Above Value
+ Replaced Value
+ Text Position
+ Below Value
+ Postfix Value
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/MatchConfigWindowLegacy.xaml b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/MatchConfigWindowLegacy.xaml
new file mode 100644
index 000000000..39971e31c
--- /dev/null
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/MatchConfigWindowLegacy.xaml
@@ -0,0 +1,48 @@
+
+
+
+
+
+ Halftone
+ Transparency
+
+
+ Projection Line Color
+ Projection Line Pattern
+ Projection Line Weight
+ Projection Fill Color
+ Projection Fill Pattern
+ Projection Fill Pattern Visibility
+
+
+
+ Cut Line Color
+ Cut Line Pattern
+ Cut Line Weight
+ Cut Fill Color
+ Cut Fill Pattern
+ Cut Fill Pattern Visibility
+
+
+
+
+
+ Replaced Value
+ Text Position
+ Above Value
+ Below Value
+ Prefix Value
+ Postfix Value
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/config.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/config.py
index c28637cdb..c4b2c0eb5 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/config.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/config.py
@@ -1,5 +1,6 @@
"""Configuration window for Match tool."""
-
+#pylint: disable=E0401,C0111,W0613
+from pyrevit import HOST_APP
from pyrevit import forms
from pyrevit import script
@@ -10,28 +11,46 @@ def __init__(self, xaml_file_name):
self._config = script.get_config()
+ # base
self.halftone.IsChecked = \
self._config.get_option('halftone', True)
self.transparency.IsChecked = \
self._config.get_option('transparency', True)
+
+ # projection lines
self.proj_line_color.IsChecked = \
self._config.get_option('proj_line_color', True)
self.proj_line_pattern.IsChecked = \
self._config.get_option('proj_line_pattern', True)
self.proj_line_weight.IsChecked = \
self._config.get_option('proj_line_weight', True)
+
+ # projection forground pattern
self.proj_fill_color.IsChecked = \
self._config.get_option('proj_fill_color', True)
self.proj_fill_pattern.IsChecked = \
self._config.get_option('proj_fill_pattern', True)
self.proj_fill_pattern_visibility.IsChecked = \
self._config.get_option('proj_fill_pattern_visibility', True)
+
+ # projection background pattern (Revit >= 2019)
+ if HOST_APP.is_newer_than(2019, or_equal=True):
+ self.proj_bg_fill_color.IsChecked = \
+ self._config.get_option('proj_bg_fill_color', True)
+ self.proj_bg_fill_pattern.IsChecked = \
+ self._config.get_option('proj_bg_fill_pattern', True)
+ self.proj_bg_fill_pattern_visibility.IsChecked = \
+ self._config.get_option('proj_bg_fill_pattern_visibility', True)
+
+ # cut lines
self.cut_line_color.IsChecked = \
self._config.get_option('cut_line_color', True)
self.cut_line_pattern.IsChecked = \
self._config.get_option('cut_line_pattern', True)
self.cut_line_weight.IsChecked = \
self._config.get_option('cut_line_weight', True)
+
+ # cut forground pattern
self.cut_fill_color.IsChecked = \
self._config.get_option('cut_fill_color', True)
self.cut_fill_pattern.IsChecked = \
@@ -39,6 +58,16 @@ def __init__(self, xaml_file_name):
self.cut_fill_pattern_visibility.IsChecked = \
self._config.get_option('cut_fill_pattern_visibility', True)
+ # cut background pattern (Revit >= 2019)
+ if HOST_APP.is_newer_than(2019, or_equal=True):
+ self.cut_bg_fill_color.IsChecked = \
+ self._config.get_option('cut_bg_fill_color', True)
+ self.cut_bg_fill_pattern.IsChecked = \
+ self._config.get_option('cut_bg_fill_pattern', True)
+ self.cut_bg_fill_pattern_visibility.IsChecked = \
+ self._config.get_option('cut_bg_fill_pattern_visibility', True)
+
+ # dim overrides
self.dim_override.IsChecked = \
self._config.get_option('dim_override', True)
self.dim_textposition.IsChecked = \
@@ -59,12 +88,18 @@ def set_all(self, state):
self.proj_fill_color.IsChecked = state
self.proj_fill_pattern.IsChecked = state
self.proj_fill_pattern_visibility.IsChecked = state
+ self.proj_bg_fill_color.IsChecked = state
+ self.proj_bg_fill_pattern.IsChecked = state
+ self.proj_bg_fill_pattern_visibility.IsChecked = state
self.cut_line_color.IsChecked = state
self.cut_line_pattern.IsChecked = state
self.cut_line_weight.IsChecked = state
self.cut_fill_color.IsChecked = state
self.cut_fill_pattern.IsChecked = state
self.cut_fill_pattern_visibility.IsChecked = state
+ self.cut_bg_fill_color.IsChecked = state
+ self.cut_bg_fill_pattern.IsChecked = state
+ self.cut_bg_fill_pattern_visibility.IsChecked = state
self.dim_override.IsChecked = state
self.dim_textposition.IsChecked = state
@@ -89,6 +124,11 @@ def save_options(self, sender, args):
self._config.proj_fill_pattern = self.proj_fill_pattern.IsChecked
self._config.proj_fill_pattern_visibility = \
self.proj_fill_pattern_visibility.IsChecked
+ self._config.proj_bg_fill_color = self.proj_bg_fill_color.IsChecked
+ self._config.proj_bg_fill_pattern = self.proj_bg_fill_pattern.IsChecked
+ self._config.proj_bg_fill_pattern_visibility = \
+ self.proj_bg_fill_pattern_visibility.IsChecked
+
self._config.cut_line_color = self.cut_line_color.IsChecked
self._config.cut_line_pattern = self.cut_line_pattern.IsChecked
self._config.cut_line_weight = self.cut_line_weight.IsChecked
@@ -96,6 +136,10 @@ def save_options(self, sender, args):
self._config.cut_fill_pattern = self.cut_fill_pattern.IsChecked
self._config.cut_fill_pattern_visibility = \
self.cut_fill_pattern_visibility.IsChecked
+ self._config.cut_bg_fill_color = self.cut_bg_fill_color.IsChecked
+ self._config.cut_bg_fill_pattern = self.cut_bg_fill_pattern.IsChecked
+ self._config.cut_bg_fill_pattern_visibility = \
+ self.cut_bg_fill_pattern_visibility.IsChecked
self._config.dim_override = self.dim_override.IsChecked
self._config.dim_textposition = self.dim_textposition.IsChecked
@@ -108,4 +152,7 @@ def save_options(self, sender, args):
self.Close()
-MatchPropConfigWindow('MatchConfigWindow.xaml').ShowDialog()
+if HOST_APP.is_newer_than(2019, or_equal=True):
+ MatchPropConfigWindow('MatchConfigWindow.xaml').ShowDialog()
+else:
+ MatchPropConfigWindow('MatchConfigWindowLegacy.xaml').ShowDialog()
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/script.py
index 57685c018..f521e6aee 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Match.pushbutton/script.py
@@ -1,9 +1,11 @@
-from pyrevit import revit, DB, UI
+#pylint: disable=E0401,C0111,W0613,C0103
+from pyrevit import HOST_APP
+from pyrevit import revit, DB
from pyrevit import script
from pyrevit import forms
-__helpurl__ = "https://www.youtube.com/watch?v=SrjyyGvarhw"
+__helpurl__ = "{{docpath}}SrjyyGvarhw"
__doc__ = 'Pick the source object that has the element graphics override '\
'you like to match to, and then pick the destination objects '\
@@ -33,49 +35,106 @@ def setup_dim_overrides_per_config(from_dim, to_dim):
def setup_style_per_config(from_style, to_style):
+ # base
if my_config.get_option('halftone', True):
to_style.SetHalftone(from_style.Halftone)
if my_config.get_option('transparency', True):
to_style.SetSurfaceTransparency(from_style.Transparency)
+ # projections
if my_config.get_option('proj_line_color', True):
to_style.SetProjectionLineColor(from_style.ProjectionLineColor)
-
if my_config.get_option('proj_line_pattern', True):
to_style.SetProjectionLinePatternId(from_style.ProjectionLinePatternId)
-
if my_config.get_option('proj_line_weight', True):
to_style.SetProjectionLineWeight(from_style.ProjectionLineWeight)
- if my_config.get_option('proj_fill_color', True):
- to_style.SetProjectionFillColor(from_style.ProjectionFillColor)
-
- if my_config.get_option('proj_fill_pattern', True):
- to_style.SetProjectionFillPatternId(from_style.ProjectionFillPatternId)
-
- if my_config.get_option('proj_fill_pattern_visibility', True):
- to_style.SetProjectionFillPatternVisible(
- from_style.IsProjectionFillPatternVisible
- )
-
+ if HOST_APP.is_newer_than(2019, or_equal=True):
+ if my_config.get_option('proj_fill_color', True):
+ to_style.SetSurfaceForegroundPatternColor(
+ from_style.SurfaceForegroundPatternColor
+ )
+ if my_config.get_option('proj_fill_pattern', True):
+ to_style.SetSurfaceForegroundPatternId(
+ from_style.SurfaceForegroundPatternId
+ )
+ if my_config.get_option('proj_fill_pattern_visibility', True):
+ to_style.SetSurfaceForegroundPatternVisible(
+ from_style.IsSurfaceForegroundPatternVisible
+ )
+ if my_config.get_option('proj_bg_fill_color', True):
+ to_style.SetSurfaceBackgroundPatternColor(
+ from_style.SurfaceBackgroundPatternColor
+ )
+ if my_config.get_option('proj_bg_fill_pattern', True):
+ to_style.SetSurfaceBackgroundPatternId(
+ from_style.SurfaceBackgroundPatternId
+ )
+ if my_config.get_option('proj_bg_fill_pattern_visibility', True):
+ to_style.SetSurfaceBackgroundPatternVisible(
+ from_style.IsSurfaceBackgroundPatternVisible
+ )
+ else:
+ if my_config.get_option('proj_fill_color', True):
+ to_style.SetProjectionFillColor(
+ from_style.ProjectionFillColor
+ )
+ if my_config.get_option('proj_fill_pattern', True):
+ to_style.SetProjectionFillPatternId(
+ from_style.ProjectionFillPatternId
+ )
+ if my_config.get_option('proj_fill_pattern_visibility', True):
+ to_style.SetProjectionFillPatternVisible(
+ from_style.IsProjectionFillPatternVisible
+ )
+
+ # cuts
if my_config.get_option('cut_line_color', True):
to_style.SetCutLineColor(from_style.CutLineColor)
-
if my_config.get_option('cut_line_pattern', True):
to_style.SetCutLinePatternId(from_style.CutLinePatternId)
-
if my_config.get_option('cut_line_weight', True):
to_style.SetCutLineWeight(from_style.CutLineWeight)
- if my_config.get_option('cut_fill_color', True):
- to_style.SetCutFillColor(from_style.CutFillColor)
-
- if my_config.get_option('cut_fill_pattern', True):
- to_style.SetCutFillPatternId(from_style.CutFillPatternId)
-
- if my_config.get_option('cut_fill_pattern_visibility', True):
- to_style.SetCutFillPatternVisible(from_style.IsCutFillPatternVisible)
+ if HOST_APP.is_newer_than(2019, or_equal=True):
+ if my_config.get_option('cut_fill_color', True):
+ to_style.SetCutForegroundPatternColor(
+ from_style.CutForegroundPatternColor
+ )
+ if my_config.get_option('cut_fill_pattern', True):
+ to_style.SetCutForegroundPatternId(
+ from_style.CutForegroundPatternId
+ )
+ if my_config.get_option('cut_fill_pattern_visibility', True):
+ to_style.SetCutForegroundPatternVisible(
+ from_style.IsCutForegroundPatternVisible
+ )
+ if my_config.get_option('cut_bg_fill_color', True):
+ to_style.SetCutBackgroundPatternColor(
+ from_style.CutBackgroundPatternColor
+ )
+ if my_config.get_option('cut_bg_fill_pattern', True):
+ to_style.SetCutBackgroundPatternId(
+ from_style.CutBackgroundPatternId
+ )
+ if my_config.get_option('cut_bg_fill_pattern_visibility', True):
+ to_style.SetCutBackgroundPatternVisible(
+ from_style.IsCutBackgroundPatternVisible
+ )
+ else:
+ if my_config.get_option('cut_fill_color', True):
+ to_style.SetCutFillColor(
+ from_style.CutFillColor
+ )
+ if my_config.get_option('cut_fill_pattern', True):
+ to_style.SetCutFillPatternId(
+ from_style.CutFillPatternId
+ )
+ if my_config.get_option('cut_fill_pattern_visibility', True):
+ to_style.SetCutFillPatternVisible(
+ from_style.IsCutFillPatternVisible
+ )
def get_source_style(element_id):
@@ -110,12 +169,14 @@ def pick_and_match_styles(src_style):
if not dest_element:
break
+ dest_element_ids = [dest_element.Id]
+ dest_element_ids.extend(dest_element.GetSubComponentIds())
with revit.Transaction('Match Graphics Overrides'):
- revit.activeview.SetElementOverrides(dest_element.Id,
- src_style)
+ for dest_elid in dest_element_ids:
+ revit.activeview.SetElementOverrides(dest_elid, src_style)
-# fixme: modify to remember source style
+# FIXME: modify to remember source style
with forms.WarningBar(title='Pick source object:'):
source_element = revit.pick_element()
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Batch Import Pat Files.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Batch Import Pat Files.pushbutton/script.py
index 1b81688cf..2c0512bce 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Batch Import Pat Files.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Batch Import Pat Files.pushbutton/script.py
@@ -8,7 +8,6 @@
from pyrevit import forms
from pyrevit import script
-__author__ = "Ehsan Iran-Nejad"
logger = script.get_logger()
output = script.get_output()
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py
index 0f8ae89ad..394ddfeb0 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/patmaker.py
@@ -16,6 +16,8 @@
HALF_PI = PI/2.0
ZERO_TOL = 5e-06
+COORD_RESOLUTION = 8
+
# 0.5 < MODEL < 848.5 inches, source: http://hatchkit.com.au/faq.php#Tip7
MAX_MODEL_DOMAIN = 100.0
@@ -43,8 +45,8 @@
class _PatternPoint:
def __init__(self, u_point, v_point):
- self.u = u_point
- self.v = v_point
+ self.u = round(u_point, COORD_RESOLUTION)
+ self.v = round(v_point, COORD_RESOLUTION)
def __repr__(self):
return '<_PatternPoint U:{0:.20f} V:{1:.20f}>'.format(self.u, self.v)
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/script.py
index 6d7a06c94..f200efb47 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/Patterns.splitpushbutton/Make Pattern.pushbutton/script.py
@@ -1,9 +1,9 @@
+#pylint: disable=C0111,E0401,C0103,W0201,W0613
import re
-from pyrevit import coreutils
from pyrevit.coreutils import pyutils
from pyrevit import forms
-from pyrevit import revit, DB, UI
+from pyrevit import revit, DB
from pyrevit import script
import patmaker
@@ -11,7 +11,7 @@
__title__ = 'Make\nPattern'
-__helpurl__ = 'https://www.youtube.com/watch?v=H7b8hjHbauE'
+__helpurl__ = '{{docpath}}H7b8hjHbauE'
__doc__ = 'Draw your pattern tile in a detail view using detail lines, '\
'curves, circles or ellipses, or even filled regions.\n'\
@@ -35,14 +35,19 @@
selection = revit.get_selection()
-accpeted_lines = [DB.DetailLine,
- DB.DetailArc,
- DB.DetailEllipse,
- DB.DetailNurbSpline]
-accpeted_curves = [DB.Arc,
- DB.Ellipse,
- DB.NurbSpline]
+acceptable_lines = (DB.DetailLine,
+ DB.DetailArc,
+ DB.DetailEllipse,
+ DB.DetailNurbSpline,
+ DB.ModelLine,
+ DB.ModelArc,
+ DB.ModelEllipse,
+ DB.ModelNurbSpline)
+
+acceptable_curves = (DB.Arc,
+ DB.Ellipse,
+ DB.NurbSpline)
detail_line_types = [DB.DetailLine,
DB.DetailEllipse,
@@ -59,7 +64,7 @@
readonly_patterns = ['solid fill']
-PICK_COORD_RESOLUTION = 10
+PICK_COORD_RESOLUTION = 8
class MakePatternWindow(forms.WPFWindow):
@@ -103,6 +108,10 @@ def export_scale(self):
# 12 for feet to inch, 304.8 for feet to mm
return 12.0 if self.export_units_cb.SelectedItem == 'INCH' else 304.8
+ @staticmethod
+ def round_coord(coord):
+ return round(coord, PICK_COORD_RESOLUTION)
+
def update_fillgrid(self, rvt_fillgrid, scale):
ext_origin = rvt_fillgrid.Origin
rvt_fillgrid.Origin = DB.UV(ext_origin.U * scale,
@@ -115,12 +124,18 @@ def update_fillgrid(self, rvt_fillgrid, scale):
return rvt_fillgrid
+ def grab_geom_curves(self, line):
+ return line.GeometryCurve
+
+ def convert_to_acceptable_line(self):
+ pass
+
def cleanup_selection(self, rvt_elements, for_model=True):
- lines = []
+ geom_curves = []
adjusted_fillgrids = []
for element in rvt_elements:
- if type(element) in accpeted_lines:
- lines.append(element)
+ if isinstance(element, acceptable_lines):
+ geom_curves.append(self.grab_geom_curves(element))
elif isinstance(element, DB.FilledRegion):
frtype = revit.doc.GetElement(element.GetTypeId())
fillpat_element = revit.doc.GetElement(frtype.FillPatternId)
@@ -134,7 +149,7 @@ def cleanup_selection(self, rvt_elements, for_model=True):
else:
adjusted_fillgrids.extend(fillgrids)
- return lines, adjusted_fillgrids
+ return geom_curves, adjusted_fillgrids
def setup_patnames(self):
existing_pats = DB.FilteredElementCollector(revit.doc)\
@@ -170,9 +185,6 @@ def setup_export_units(self):
self.export_units_cb.SelectedIndex = 0
def pick_domain(self):
- def round_domain_coord(coord):
- return round(coord, PICK_COORD_RESOLUTION)
-
# ask user for origin and max domain points
with forms.WarningBar(title='Pick origin point (bottom-left '
'corner of the pattern area):'):
@@ -182,15 +194,18 @@ def round_domain_coord(coord):
'of the pattern area:'):
pat_topright = revit.pick_point()
if pat_topright:
- return (round_domain_coord(pat_bottomleft.X),
- round_domain_coord(pat_bottomleft.Y)), \
- (round_domain_coord(pat_topright.X),
- round_domain_coord(pat_topright.Y))
+ return (MakePatternWindow.round_coord(pat_bottomleft.X),
+ MakePatternWindow.round_coord(pat_bottomleft.Y)), \
+ (MakePatternWindow.round_coord(pat_topright.X),
+ MakePatternWindow.round_coord(pat_topright.Y))
return False
def make_pattern_line(self, start_xyz, end_xyz):
- return (start_xyz.X, start_xyz.Y), (end_xyz.X, end_xyz.Y)
+ return (MakePatternWindow.round_coord(start_xyz.X),
+ MakePatternWindow.round_coord(start_xyz.Y)), \
+ (MakePatternWindow.round_coord(end_xyz.X),
+ MakePatternWindow.round_coord(end_xyz.Y))
def export_pattern(self, export_dir):
patname = self.pat_name_cb.SelectedItem
@@ -216,14 +231,13 @@ def export_pattern(self, export_dir):
def create_pattern(self, domain, export_only=False, export_path=None):
# cleanup selection (pick only acceptable curves)
- self.selected_lines, self.selected_fillgrids = \
+ self.selected_geom_curves, self.selected_fillgrids = \
self.cleanup_selection(self._selection,
for_model=self.is_model_pat)
line_tuples = []
- for det_line in self.selected_lines:
- geom_curve = det_line.GeometryCurve
- if type(geom_curve) in accpeted_curves:
+ for geom_curve in self.selected_geom_curves:
+ if isinstance(geom_curve, acceptable_curves):
tes_points = [tp for tp in geom_curve.Tessellate()]
for xyz1, xyz2 in pyutils.pairwise(tes_points, step=1):
line_tuples.append(self.make_pattern_line(xyz1, xyz2))
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Overkill.pushbutton/icon.png b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Overkill.pushbutton/icon.png
new file mode 100644
index 000000000..0d0afe410
Binary files /dev/null and b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Overkill.pushbutton/icon.png differ
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Overkill.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Overkill.pushbutton/script.py
new file mode 100644
index 000000000..2816d5195
--- /dev/null
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Overkill.pushbutton/script.py
@@ -0,0 +1,200 @@
+"""Deletes the lines overlapped by other lines (similar to AutoCAD Overkill)"""
+
+#pylint: disable=E0401,C0103
+import math
+from collections import namedtuple
+
+from pyrevit.framework import List
+from pyrevit import revit, DB
+from pyrevit import forms
+from pyrevit import script
+
+
+__author__ = "Ehsan Iran-Nejad\ntylerk"
+
+logger = script.get_logger()
+output = script.get_output()
+
+INCLUDE_STYLE = True
+VIEW_SPECIFIC = True
+
+DomainBound = namedtuple('DomainBound', ['x', 'y', 'dlid'])
+
+
+class DetailLineDomain(object):
+ def __init__(self, dline, include_style=False):
+ # calculate domain parameters
+ dvector = dline.GeometryCurve.Direction
+ p1 = dline.GeometryCurve.GetEndPoint(0)
+ p2 = dline.GeometryCurve.GetEndPoint(1)
+ self.offset = \
+ self.shortest_dist(p1.X, p1.Y, p2.X, p2.Y, dvector.X, dvector.Y)
+ self.direction = dvector.X, dvector.Y
+ self.reverse = (dvector.X * dvector.Y) < 0
+ self.weight = None
+ if include_style:
+ self.weight = DetailLineDomain.get_style_weight(dline)
+
+ # set domain boundary
+ self.max = DomainBound(x=p1.X, y=p1.Y, dlid=dline.Id.IntegerValue)
+ self.min = DomainBound(x=p2.X, y=p2.Y, dlid=dline.Id.IntegerValue)
+ if self.max.x < self.min.x \
+ or self.min.x > self.max.x:
+ self.min, self.max = self.max, self.min
+
+ # prepare a list for overlapping curves
+ self.bounded = set()
+
+ def __repr__(self):
+ return '<%s max=%s, min=%s weight=%s>' % (
+ self.__class__.__name__,
+ self.max,
+ self.min,
+ self.weight)
+
+ def __hash__(self):
+ d1 = self.direction[0]
+ d2 = self.direction[1]
+ if d1 < 0 and d2 < 0:
+ d1 = abs(d1)
+ d2 = abs(d2)
+ elif d1 < 0 and d2 > 0:
+ d1 = abs(d1)
+ d2 = -d2
+ return hash(('{:.3f}'.format(d1),
+ '{:.3f}'.format(d2),
+ '{:.3f}'.format(self.offset),
+ self.weight))
+
+ def __eq__(self, other):
+ return hash(self) == hash(other)
+
+ @staticmethod
+ def shortest_dist(x1, y1, x2, y2, x0, y0):
+ # https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
+ # line passes thru (x1, y1), (x2, y2)
+ # point is (x0, y0)
+ return (abs(x0*(y2-y1)-y0*(x2-x1)+x2*y1-y2*x1) /
+ math.sqrt((y2-y1)**2 + (x2-x1)**2))
+
+ @staticmethod
+ def get_style_weight(dline):
+ graphic_style_cat = dline.LineStyle.GraphicsStyleCategory
+ graphic_style_type = dline.LineStyle.GraphicsStyleType
+ return graphic_style_cat.GetLineWeight(graphic_style_type)
+
+ def dline_ids(self):
+ return list(set([self.max.dlid, self.min.dlid]))
+
+ def extends_max(self, dbound):
+ if self.reverse:
+ if dbound.x > self.max.x:
+ if dbound.y < self.max.y:
+ return True
+ else:
+ if dbound.x > self.max.x:
+ if dbound.y > self.max.y:
+ return True
+ return False
+
+ def extends_min(self, dbound):
+ if self.reverse:
+ if dbound.x < self.min.x:
+ if dbound.y > self.min.y:
+ return True
+ else:
+ if dbound.x < self.min.x:
+ if dbound.y < self.min.y:
+ return True
+ return False
+
+ def merge(self, dldomain):
+ extends_max = self.extends_max(dldomain.max)
+ extends_min = self.extends_min(dldomain.min)
+ if extends_max and extends_min:
+ logger.debug('Domain overlaps existing: %s', dldomain)
+ logger.debug('Mark as bounded: %s', self.dline_ids())
+ self.bounded.update(self.dline_ids())
+ logger.debug('Extending max: %s -> %s', self.max, dldomain.max)
+ self.max = dldomain.max
+ logger.debug('Extending min: %s -> %s', self.min, dldomain.min)
+ self.min = dldomain.min
+ elif not extends_max and not extends_min:
+ logger.debug('Domain is contained: %s', dldomain)
+ logger.debug('Mark as bounded: %s', dldomain.dline_ids())
+ self.bounded.update(dldomain.dline_ids())
+
+
+class DetailLineDomainCollection(object):
+ def __init__(self, include_style=False):
+ self.domains = []
+ self._include_style = include_style
+
+ def __iter__(self):
+ return iter(self.domains)
+
+ def extend(self, dline):
+ dldomain = DetailLineDomain(dline, include_style=self._include_style)
+ if dldomain not in self.domains:
+ logger.debug('New domain %s', dldomain)
+ self.domains.append(dldomain)
+ else:
+ idx = self.domains.index(dldomain)
+ ext_dldomain = self.domains[idx]
+ logger.debug('Merging into existing domain %s', ext_dldomain)
+ ext_dldomain.merge(dldomain)
+
+
+def filter_lines(lines, view_specific):
+ if view_specific is None:
+ return lines
+ else:
+ return [x for x in lines if x.ViewSpecific == view_specific]
+
+
+# ask user for options and process
+options = ['All Lines', 'Detail Lines', 'Model Lines']
+switches = {'Consider Line Weights': True}
+selected_option, switches = \
+ forms.CommandSwitchWindow.show(
+ options,
+ switches=switches,
+ message='Pick overkill option:'
+ )
+
+if not switches['Consider Line Weights']:
+ INCLUDE_STYLE = False
+
+if selected_option == 'All Lines':
+ VIEW_SPECIFIC = None
+elif selected_option == 'Model Lines':
+ VIEW_SPECIFIC = False
+elif selected_option == 'Detail Lines':
+ VIEW_SPECIFIC = True
+
+if selected_option:
+ # collect all detail-lines in active view
+ logger.debug('Collecting detail lines in current view...')
+ detline_collector = \
+ revit.query.get_elements_by_class(DB.CurveElement,
+ view_id=revit.activeview.Id)
+
+ # collect comparison info on each detail-lines geomtery
+ logger.debug('Extracting 2d domains...')
+ detline_domaincl = DetailLineDomainCollection(include_style=INCLUDE_STYLE)
+ for detline in filter_lines(detline_collector, view_specific=VIEW_SPECIFIC):
+ logger.debug('Adding detail line to domains: %s', detline.Id.IntegerValue)
+ detline_domaincl.extend(detline)
+
+ del_count = 0
+ with revit.Transaction('Overkill'):
+ for detline_domain in detline_domaincl:
+ bounded_detline_ids = \
+ [DB.ElementId(x) for x in detline_domain.bounded]
+ del_count += len(bounded_detline_ids)
+ revit.doc.Delete(List[DB.ElementId](bounded_detline_ids))
+
+ if del_count > 0:
+ forms.alert('{} lines were removed.'.format(del_count))
+ else:
+ forms.alert('Pretty clean! No lines were removed.')
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Tag All in All Views.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Tag All in All Views.pushbutton/script.py
index e6c4c0221..281f0baef 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Tag All in All Views.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Modify.panel/edit.stack3/Edit.pulldown/Tag All in All Views.pushbutton/script.py
@@ -1,9 +1,12 @@
+"""Tag all chosen element types in all views."""
+#pylint: disable=C0103,E0401,C0111
from pyrevit import revit, DB
from pyrevit import script
from pyrevit import forms
logger = script.get_logger()
+output = script.get_output()
views = DB.FilteredElementCollector(revit.doc)\
@@ -12,7 +15,7 @@
.ToElements()
-def GetElementCenter(el, v):
+def GetElementCenter(el):
cen = el.Location.Point
z = (el.UpperLimit.Elevation + el.LimitOffset) / 2
cen = cen.Add(DB.XYZ(0, 0, z))
@@ -26,41 +29,49 @@ def tag_all_rooms():
.ToElements()
with revit.Transaction('Tag All Rooms in All Views'):
- for v in views:
+ for view in views:
for el in rooms:
- room_center = GetElementCenter(el, v)
- if type(v) in [DB.ViewSection, DB.ViewPlan]:
- logger.debug('Working on view: %s' % v.ViewName)
- roomtag = \
+ room_center = GetElementCenter(el)
+ if not room_center:
+ logger.debug('Can not detect center for element: {}',
+ output.linkify(el.Id))
+ continue
+ if isinstance(view, (DB.ViewSection, DB.ViewPlan)):
+ logger.debug('Working on view: %s' % view.ViewName)
+ room_tag = \
revit.doc.Create.NewRoomTag(
DB.LinkElementId(el.Id),
DB.UV(room_center.X, room_center.Y),
- v.Id
+ view.Id
)
- if isinstance(v, DB.ViewSection):
- roomtag.Location.Move(DB.XYZ(0, 0, room_center.Z))
+ if isinstance(view, DB.ViewSection):
+ room_tag.Location.Move(DB.XYZ(0, 0, room_center.Z))
def tag_all_spaces():
spaces = DB.FilteredElementCollector(revit.doc)\
- .OfCategory(DB.BuiltInCategory.OST_MEPSpaces)\
- .WhereElementIsNotElementType()\
- .ToElements()
+ .OfCategory(DB.BuiltInCategory.OST_MEPSpaces)\
+ .WhereElementIsNotElementType()\
+ .ToElements()
with revit.Transaction('Tag All Spaces in All Views'):
- for v in views:
+ for view in views:
for el in spaces:
- room_center = GetElementCenter(el, v)
- if type(v) in [DB.ViewSection, DB.ViewPlan]:
- logger.debug('Working on view: %s' % v.ViewName)
- roomtag = \
+ space_center = GetElementCenter(el)
+ if not space_center:
+ logger.debug('Can not detect center for element: {}',
+ output.linkify(el.Id))
+ continue
+ if isinstance(view, (DB.ViewSection, DB.ViewPlan)):
+ logger.debug('Working on view: %s' % view.ViewName)
+ space_tag = \
revit.doc.Create.NewRoomTag(
DB.LinkElementId(el.Id),
- DB.UV(room_center.X, room_center.Y),
- v.Id
+ DB.UV(space_center.X, space_center.Y),
+ view.Id
)
- if isinstance(v, DB.ViewSection):
- roomtag.Location.Move(DB.XYZ(0, 0, room_center.Z))
+ if isinstance(view, DB.ViewSection):
+ space_tag.Location.Move(DB.XYZ(0, 0, space_center.Z))
options_dict = {'Tag All Rooms in All Views': tag_all_rooms,
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MAppend.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MAppend.pushbutton/script.py
index 357161686..0c1650daf 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MAppend.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MAppend.pushbutton/script.py
@@ -5,7 +5,7 @@
__context__ = 'Selection'
-__helpurl__ = 'https://www.youtube.com/watch?v=pAM-ARIXXLw'
+__helpurl__ = '{{docpath}}pAM-ARIXXLw'
__doc__ = 'Append current selection to memory.\n'\
'Works like the M+ button in a calculator. '\
'This is a project-dependent memory. Every project has its own '\
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MRead.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MRead.pushbutton/script.py
index c26c428c4..c11be244b 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MRead.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MRead.pushbutton/script.py
@@ -5,7 +5,7 @@
from pyrevit import revit, DB
-__helpurl__ = 'https://www.youtube.com/watch?v=pAM-ARIXXLw'
+__helpurl__ = '{{docpath}}pAM-ARIXXLw'
__doc__ = 'Read selection from memory.\n'\
'Works like the MR button in a calculator. '\
'This is a project-dependent memory. Every project has its own '\
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MWrite.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MWrite.pushbutton/script.py
index 8ae1a4197..e08a39dba 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MWrite.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/mema.stack3/MWrite.pushbutton/script.py
@@ -5,7 +5,7 @@
__context__ = 'Selection'
-__helpurl__ = 'https://www.youtube.com/watch?v=pAM-ARIXXLw'
+__helpurl__ = '{{docpath}}pAM-ARIXXLw'
__doc__ = 'Clear memory and Append current selection.\n'\
'Works like the MC and M+ button in a calculator. '\
'This is a project-dependent memory. Every project has its own '\
diff --git a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/memo.stack3/Copy State.pushbutton/script.py b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/memo.stack3/Copy State.pushbutton/script.py
index 24440411a..183587610 100644
--- a/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/memo.stack3/Copy State.pushbutton/script.py
+++ b/extensions/pyRevitTools.extension/pyRevit.tab/Selection.panel/memo.stack3/Copy State.pushbutton/script.py
@@ -13,8 +13,8 @@
' view to memory. e.g. Visibility Graphics settings or'\
' Zoom state. Run it how see how it works.'
-__author__ = 'Gui Talarico | github.com/gtalarico\n'\
- 'Ehsan Iran-Nejad | eirannejad@gmail.com'
+__author__ = 'Gui Talarico\n'\
+ 'Ehsan Iran-Nejad'
class Point:
diff --git a/pyRevitfile b/pyRevitfile
index 464008b7c..a9a8a0570 100644
--- a/pyRevitfile
+++ b/pyRevitfile
@@ -34,4 +34,5 @@ description = 'Latest Release Candidate (RC1)'
[deployments]
core = ['bin', 'pyrevitlib', 'site-packages', 'pyRevitfile']
base = ['bin', 'extensions/pyRevitCore.extension', 'extensions/pyRevitTools.extension', 'pyrevitlib', 'site-packages', 'pyRevitfile']
+basepublic = ['bin', 'extensions/pyRevitCore.extension', 'extensions/pyRevitTools.extension', 'extensions/pyRevitTutor.extension', 'pyrevitlib', 'site-packages', 'pyRevitfile']
basex = ['bin', 'extensions', 'pyrevitlib', 'site-packages', 'pyRevitfile']
\ No newline at end of file
diff --git a/pyrevitlib/pyrevit/__init__.py b/pyrevitlib/pyrevit/__init__.py
index 3f75a3e7c..b76a05cdd 100644
--- a/pyrevitlib/pyrevit/__init__.py
+++ b/pyrevitlib/pyrevit/__init__.py
@@ -38,7 +38,7 @@
PYREVIT_ADDON_NAME = 'pyRevit'
VERSION_MAJOR = 4
VERSION_MINOR = 6
-BUILD_METADATA = '-beta'
+BUILD_METADATA = '-beta2'
# -----------------------------------------------------------------------------
# config environment paths
@@ -281,13 +281,16 @@ def proc_screen_scalefactor(self):
scaled_width = screen.PrimaryScreen.WorkingArea.Width
return abs(scaled_width / actual_wdith)
- def is_newer_than(self, version):
+ def is_newer_than(self, version, or_equal=False):
"""bool: Return True if host app is newer than provided version.
Args:
version (str or int): version to check against.
"""
- return int(self.version) > int(version)
+ if or_equal:
+ return int(self.version) >= int(version)
+ else:
+ return int(self.version) > int(version)
def is_older_than(self, version):
"""bool: Return True if host app is older than provided version.
diff --git a/pyrevitlib/pyrevit/coreutils/configparser.py b/pyrevitlib/pyrevit/coreutils/configparser.py
index cb2212bdf..929bbb06f 100644
--- a/pyrevitlib/pyrevit/coreutils/configparser.py
+++ b/pyrevitlib/pyrevit/coreutils/configparser.py
@@ -1,4 +1,5 @@
"""Base module for pyRevit config parsing."""
+import ast
import ConfigParser
from ConfigParser import NoOptionError, NoSectionError
@@ -41,7 +42,7 @@ def __getattr__(self, param_name):
if value.isdecimal():
value = int(value)
- return eval(value) #pylint: disable=W0123
+ return ast.literal_eval(value) #pylint: disable=W0123
except Exception:
return value
except (NoOptionError, NoSectionError):
diff --git a/pyrevitlib/pyrevit/coreutils/ribbon.py b/pyrevitlib/pyrevit/coreutils/ribbon.py
index f84a78a6f..299adf03f 100644
--- a/pyrevitlib/pyrevit/coreutils/ribbon.py
+++ b/pyrevitlib/pyrevit/coreutils/ribbon.py
@@ -251,6 +251,57 @@ def get_updated_items(self):
def get_unchanged_items(self):
return self.get_flagged_children(state=False)
+ def reorder_before(self, litem_name, ritem_name):
+ apiobj = self.get_rvtapi_object()
+ litem_idx = ritem_idx = None
+ if hasattr(apiobj, 'Panels'):
+ for item in apiobj.Panels:
+ if item.Source.AutomationName == litem_name:
+ litem_idx = apiobj.Panels.IndexOf(item)
+ elif item.Source.AutomationName == ritem_name:
+ ritem_idx = apiobj.Panels.IndexOf(item)
+ if litem_idx and ritem_idx:
+ if litem_idx < ritem_idx:
+ apiobj.Panels.Move(litem_idx, ritem_idx - 1)
+ elif litem_idx > ritem_idx:
+ apiobj.Panels.Move(litem_idx, ritem_idx)
+
+ def reorder_beforeall(self, litem_name):
+ apiobj = self.get_rvtapi_object()
+ litem_idx = None
+ if hasattr(apiobj, 'Panels'):
+ for item in apiobj.Panels:
+ if item.Source.AutomationName == litem_name:
+ litem_idx = apiobj.Panels.IndexOf(item)
+ if litem_idx:
+ apiobj.Panels.Move(litem_idx, 0)
+
+ def reorder_after(self, litem_name, ritem_name):
+ apiobj = self.get_rvtapi_object()
+ litem_idx = ritem_idx = None
+ if hasattr(apiobj, 'Panels'):
+ for item in apiobj.Panels:
+ if item.Source.AutomationName == litem_name:
+ litem_idx = apiobj.Panels.IndexOf(item)
+ elif item.Source.AutomationName == ritem_name:
+ ritem_idx = apiobj.Panels.IndexOf(item)
+ if litem_idx and ritem_idx:
+ if litem_idx < ritem_idx:
+ apiobj.Panels.Move(litem_idx, ritem_idx)
+ elif litem_idx > ritem_idx:
+ apiobj.Panels.Move(litem_idx, ritem_idx + 1)
+
+ def reorder_afterall(self, litem_name):
+ apiobj = self.get_rvtapi_object()
+ litem_idx = None
+ if hasattr(apiobj, 'Panels'):
+ for item in apiobj.Panels:
+ if item.Source.AutomationName == litem_name:
+ litem_idx = apiobj.Panels.IndexOf(item)
+ if litem_idx:
+ max_idx = len(apiobj.Panels) - 1
+ apiobj.Panels.Move(litem_idx, max_idx)
+
# Classes holding existing native ui elements
# (These elements are native and can not be modified) --------------------------
@@ -1035,7 +1086,7 @@ class _PyRevitUI(_GenericPyRevitUIContainer):
ribbon_tab = _GenericPyRevitUIContainer._get_component
- def __init__(self):
+ def __init__(self, all_native=False):
_GenericPyRevitUIContainer.__init__(self)
# Revit does not have any method to get a list of current tabs.
@@ -1054,7 +1105,8 @@ def __init__(self):
# pyrevit tabs (PYREVIT_TAB_IDENTIFIER) anyway.
# if revit_ui_tab.IsVisible
try:
- if _PyRevitRibbonTab.check_pyrevit_tab(revit_ui_tab):
+ if not all_native \
+ and _PyRevitRibbonTab.check_pyrevit_tab(revit_ui_tab):
new_pyrvt_tab = _PyRevitRibbonTab(revit_ui_tab)
else:
new_pyrvt_tab = _RevitNativeRibbonTab(revit_ui_tab)
@@ -1114,7 +1166,7 @@ def create_ribbon_tab(self, tab_name, update_if_exists=False):
# Public function to return an instance of _PyRevitUI which is used
# to interact with current ui --------------------------------------------------
-def get_current_ui():
+def get_current_ui(all_native=False):
"""Revit UI Wrapper class for interacting with current pyRevit UI.
Returned class provides min required functionality for user interaction
@@ -1127,7 +1179,7 @@ def get_current_ui():
:return: Returns an instance of _PyRevitUI that contains info on current ui
:rtype: _PyRevitUI
"""
- return _PyRevitUI()
+ return _PyRevitUI(all_native=all_native)
def get_uibutton(command_unique_name):
diff --git a/pyrevitlib/pyrevit/extensions/genericcomps.py b/pyrevitlib/pyrevit/extensions/genericcomps.py
index 53084094b..346d30b34 100644
--- a/pyrevitlib/pyrevit/extensions/genericcomps.py
+++ b/pyrevitlib/pyrevit/extensions/genericcomps.py
@@ -1,6 +1,8 @@
"""Generic extension components."""
import os
import os.path as op
+import re
+from collections import namedtuple
from pyrevit import HOST_APP, PyRevitException
from pyrevit import coreutils
@@ -11,6 +13,9 @@
mlogger = coreutils.logger.get_logger(__name__)
+LayoutDirective = namedtuple('LayoutDirective', ['type', 'item', 'target'])
+
+
class GenericComponent(object):
type_id = None
@@ -117,7 +122,7 @@ class GenericUIContainer(GenericUIComponent):
def __init__(self):
GenericUIComponent.__init__(self)
self._sub_components = []
- self.layout_list = None
+ self.layout = self.layout_items = None
self.name = self.ui_title = None
def __init_from_dir__(self, ext_dir):
@@ -138,8 +143,8 @@ def __init_from_dir__(self, ext_dir):
if self.library_path:
self.syspath_search_paths.append(self.library_path)
- self.layout_list = self._read_layout_file()
- mlogger.debug('Layout is: %s', self.layout_list)
+ self._read_layout_file() # sets self.layout and self.layout_items
+ mlogger.debug('Layout is: %s', self.layout_items)
full_file_path = op.join(self.directory, exts.DEFAULT_ICON_FILE)
self.icon_file = full_file_path if op.exists(full_file_path) else None
@@ -149,24 +154,32 @@ def __init_from_dir__(self, ext_dir):
def __iter__(self):
return iter(self._get_components_per_layout())
+ @staticmethod
+ def _remove_layout_directives(layout_items):
+ cleaned_items = []
+ for litem in layout_items:
+ cleaned_items.append(re.sub(r'\[.+\]', '', litem))
+ return cleaned_items
+
def _read_layout_file(self):
full_file_path = op.join(self.directory, exts.DEFAULT_LAYOUT_FILE_NAME)
if op.exists(full_file_path):
layout_file = open(op.join(self.directory,
exts.DEFAULT_LAYOUT_FILE_NAME), 'r')
- # return [x.replace('\n', '') for x in layout_file.readlines()]
- return layout_file.read().splitlines()
+ self.layout = layout_file.read().splitlines()
+ self.layout_items = \
+ GenericUIContainer._remove_layout_directives(self.layout)
else:
mlogger.debug('Container does not have layout file defined: %s',
self)
def _get_components_per_layout(self):
# if item is not listed in layout, it will not be created
- if self.layout_list and self._sub_components:
+ if self.layout_items and self._sub_components:
mlogger.debug('Reordering components per layout file...')
layout_index = 0
_processed_cmps = []
- for layout_item in self.layout_list:
+ for layout_item in self.layout_items:
for cmp_index, component in enumerate(self._sub_components): #pylint: disable=W0612
if component.name == layout_item:
_processed_cmps.append(component)
@@ -175,8 +188,8 @@ def _get_components_per_layout(self):
# insert separators and slideouts per layout definition
mlogger.debug('Adding separators and slide outs per layout...')
- last_item_index = len(self.layout_list) - 1
- for i_index, layout_item in enumerate(self.layout_list):
+ last_item_index = len(self.layout_items) - 1
+ for i_index, layout_item in enumerate(self.layout_items):
if exts.SEPARATOR_IDENTIFIER in layout_item \
and i_index < last_item_index:
separator = GenericComponent()
@@ -233,6 +246,21 @@ def get_components_of_type(self, cmp_type):
return sub_comp_list
+ def get_layout_directives(self):
+ layout_directives = []
+ if self.layout:
+ for item_def in self.layout:
+ for dir_defs in re.findall(r'(.+)\[(.+):(.*)\]', item_def):
+ source_item, directive, target_name = dir_defs
+ directive = directive.lower().strip()
+ target_name = target_name.strip()
+ layout_directives.append(
+ LayoutDirective(
+ type=directive,
+ item=source_item,
+ target=target_name
+ ))
+ return layout_directives
# superclass for all single command classes (link, push button, toggle button)
# GenericUICommand is not derived from GenericUIContainer since a command
diff --git a/pyrevitlib/pyrevit/forms/CommandSwitchWindow.xaml b/pyrevitlib/pyrevit/forms/CommandSwitchWindow.xaml
index b934f4793..7789b775b 100644
--- a/pyrevitlib/pyrevit/forms/CommandSwitchWindow.xaml
+++ b/pyrevitlib/pyrevit/forms/CommandSwitchWindow.xaml
@@ -163,8 +163,8 @@
-
-
+
+
diff --git a/pyrevitlib/pyrevit/forms/GetValueWindow.xaml b/pyrevitlib/pyrevit/forms/GetValueWindow.xaml
new file mode 100644
index 000000000..d05cb2ca6
--- /dev/null
+++ b/pyrevitlib/pyrevit/forms/GetValueWindow.xaml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pyrevitlib/pyrevit/forms/SelectFromList.xaml b/pyrevitlib/pyrevit/forms/SelectFromList.xaml
index 4a7562681..6985204a6 100644
--- a/pyrevitlib/pyrevit/forms/SelectFromList.xaml
+++ b/pyrevitlib/pyrevit/forms/SelectFromList.xaml
@@ -11,10 +11,11 @@
- Filter: