Is it possible to change the order of these filters? Pass the SPK to the top so that it overlaps others?
@guilherme.woltmann To the best of my knowledge, it is not possible to reorder the filters in an autonomous way. There isn’t any API method which gives you the order of the filters. So you cannot rearrange it automatically.
A semi-autonomous way would be to manually define an order > copy overrides > remove existing ones > apply the new order.
It would look something like this: Reorder View Filters.dyn (34.4 KB)
I’ve made it more generalized by asking for an order. If you just care about SPK being at the top, you can find the index of SPK from x.Name and reorder such that SPK’s index is on top followed by the rest indices in the default order as returned by the API call.
Graph in action:
a python solution by following this example
import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
toList = lambda x : x if hasattr(x, '__iter__') else [x]
lstViews = toList(UnwrapElement(IN[0]))
serachFilter = IN[1]
TransactionManager.Instance.EnsureInTransaction(doc)
for v in lstViews:
filterIds = v.GetFilters()
datafilters = [[filId, doc.GetElement(filId).Name, v.GetFilterOverrides(filId)] for filId in filterIds]
try:
indexFilter = [i[1] for i in datafilters].index(serachFilter)
except ValueError:
indexFilter = None
#
if indexFilter is not None:
for i in filterIds:
v.RemoveFilter(i)
#
datafilters.insert(0, datafilters.pop(indexFilter))
for fId, filterName, graphOver in datafilters:
v.AddFilter(fId)
v.SetFilterOverrides(fId, graphOver)
TransactionManager.Instance.TransactionTaskDone()
Important Note
View.GetFilters
method don’t return Filters in the order they are applied to a view (in Revit versions prior to 2021)
@c.poupin Amazing, just how I imagined.
The only thing missing is the filter visibility (and IsFilterEnabled for 2021/2022).
Would it be possible for you to add the SetFilterVisibility method so that it’s a perfect solution?
try this
the method is a little different (encapsulation of properties in a Class instance)
Important Note
before Revit 2021, View.GetFilters
method don’t return Filters in the order they are applied to a view
import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
sdkNumber = int(app.VersionNumber)
class FilterUtils():
def __init__(self, view):
self._view = view
@property
def FilterIds(self):
filterIds = self._view.GetFilters()
return filterIds
@property
def FilterNames(self):
return [doc.GetElement(x).Name for x in self.FilterIds]
@property
def FilterOverrides(self):
return [self._view.GetFilterOverrides(x) for x in self.FilterIds]
@property
def FilterVisibity(self):
return [self._view.GetFilterVisibility(x) for x in self.FilterIds]
@property
def FilterEnabled(self):
if sdkNumber > 2020:
return [self._view.GetIsFilterEnabled(x) for x in self.FilterIds]
else:
return [None] * len(self.FilterIds)
def SetFilterOnTop(self, filterName):
try:
indexFilter = self.FilterNames.index(serachFilter)
except ValueError:
indexFilter = None
#
older = self.FilterNames[:]
if indexFilter is not None and len(self.FilterIds) > 0:
datafilters = zip(self.FilterIds, self.FilterOverrides, self.FilterVisibity, self.FilterEnabled)
datafilters.insert(0, datafilters.pop(indexFilter))
#
for i in self.FilterIds:
self._view.RemoveFilter(i)
#
for fId, overrideVG, visuVG, fiEnabled in datafilters:
self._view.AddFilter(fId)
self._view.SetFilterOverrides(fId, overrideVG)
self._view.SetFilterVisibility(fId, visuVG)
if fiEnabled is not None:
self._view.SetIsFilterEnabled(fId, fiEnabled)
return self.FilterNames
toList = lambda x : x if hasattr(x, '__iter__') else [x]
lstViews = toList(UnwrapElement(IN[0]))
serachFilter = IN[1]
TransactionManager.Instance.EnsureInTransaction(doc)
for v in lstViews:
objFi = FilterUtils(v)
newOrderFilters = objFi.SetFilterOnTop(serachFilter)
TransactionManager.Instance.TransactionTaskDone()
OUT = newOrderFilters