Lorsque l'on parle de Dynamo et de la gestion des événements Revit (Évents) on pense souvent à une incompatibilité....
if this article is not in your language, use the Google Translate widget (bottom of page for Mobile version) ⬈
Par défaut Dynamo ne peut écouter les événements Revit que pendant
l'exécution du graphique et Dynamo ne peut s'exécuter qu'à l'intérieur de
l'événement inactif de Revit.
Aperçu en Vidéo
L'émetteur d'événements (Revit’s idle event) n'est déclenché que
lorsqu'aucune autre interaction ne se produit et lorsqu'il est activé, le
contexte de Revit est occupé jusqu'à ce que ce qui a déclenché l'événement
s'achève.
Une solution est d'utiliser une boucle d’évènements dans un autre Thread (avec un Winform non bloquant par exemple) ce qui permet au Thread principale de Dynamo de se terminer.
Une solution est d'utiliser une boucle d’évènements dans un autre Thread (avec un Winform non bloquant par exemple) ce qui permet au Thread principale de Dynamo de se terminer.
À quoi peut bien servir les événements Revit ?...
Un exemple de cas d'usage courant est la recherche d'éléments dans le projet et de
zoomer sur celui-ci. Pour pouvoir effectuer cette opération il faut s'assurer
au préalable que la vue ait finit de s'afficher, c'est là qu'intervient
l'utilisation d'un événement.
Voici une "reproduction" de la fonction native de Revit ou l'on effectue
une recherche d'élément par leur ID (avec entre autres la méthode RequestViewChange(View) et une fois la vue affichée on applique la méthode ShowElements(ElementId) )
Pour les opérations nécessitant une Transaction cela devient un peu plus complexe, comme on est un autre Thread (non principal) on doit faire appel à un ExternalEvent
Voici un exemple ci-dessous qui réalise les actions suivantes :
- Liste les changements de vue (via les Évents).
- Liste les éléments modifiés (via les Évents).
- Colorise la sélection d'éléments en cours si des éléments viennent d'êtres modifiés. (on pourrait également colorisé tous les éléments modifiés mais j'ai simplifié ici)
import sys
import clr
import System
from System import EventHandler, Uri
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Events import DocumentChangedEventArgs
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Events import ViewActivatedEventArgs, ViewActivatingEventArgs
from Autodesk.Revit.UI import IExternalEventHandler, ExternalEvent
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
instdoc = DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *
class MainForm(Form):
def __init__(self, ext_event, uiapp, app):
self._uiapp = uiapp
self._app = app
self._ext_event = ext_event
self.InitializeComponent()
def InitializeComponent(self):
self._buttonCancel = System.Windows.Forms.Button()
self._richTextBox1 = System.Windows.Forms.RichTextBox()
self._label1 = System.Windows.Forms.Label()
self.SuspendLayout()
# self._uiapp.ViewActivating += EventHandler[ViewActivatingEventArgs](self.ViewEvent)
# self._app.DocumentChanged += EventHandler[DocumentChangedEventArgs](self.ModifEvent)
self._delegateViewEvent = EventHandler[ViewActivatingEventArgs](self.ViewEvent)
self._delegateModifEvent = EventHandler[DocumentChangedEventArgs](self.ModifEvent)
self._uiapp.ViewActivating += self._delegateViewEvent
self._app.DocumentChanged += self._delegateModifEvent
#
# buttonCancel
self._buttonCancel.Location = System.Drawing.Point(150, 550)
self._buttonCancel.Name = "buttonStop"
self._buttonCancel.Size = System.Drawing.Size(156, 37)
self._buttonCancel.TabIndex = 0
self._buttonCancel.Text = "Stop Loop Event"
self._buttonCancel.UseVisualStyleBackColor = True
self._buttonCancel.Click += self.ButtonCancelClick
#
# richTextBox1
self._richTextBox1.Location = System.Drawing.Point(30, 37)
self._richTextBox1.Name = "richTextBox1"
self._richTextBox1.Size = System.Drawing.Size(400, 500)
self._richTextBox1.TabIndex = 1
self._richTextBox1.Text = "Processing..."
#
# label1
self._label1.Location = System.Drawing.Point(30, 9)
self._label1.Name = "label1"
self._label1.Size = System.Drawing.Size(152, 25)
self._label1.TabIndex = 2
self._label1.Text = "Revit Events"
#
# MainForm
self.ClientSize = System.Drawing.Size(480, 600)
self.Controls.Add(self._label1)
self.Controls.Add(self._richTextBox1)
self.Controls.Add(self._buttonCancel)
self.Name = "MainForm"
self.Text = "UI_Event"
self.ResumeLayout(False)
def ViewEvent(self, sender, e):
#prevent if unregister event failed
if not self.Controls[0].IsDisposed:
newViewName = e.NewActiveView.Name
currentText = self._richTextBox1.Text
self._richTextBox1.Text = currentText + "\nSwitch to View ->" + newViewName
def ModifEvent(self, sender, e):
#prevent if unregister event failed
if not self.Controls[0].IsDisposed:
lstElemNam = []
lstElemdIds = e.GetModifiedElementIds()
for xId in lstElemdIds:
elem = doc.GetElement(xId)
if elem is not None or int(xId) != 1:
lstElemNam.append(elem.Name + "Id :"+ str(xId.IntegerValue))
if len(lstElemNam) > 0:
currentText = self._richTextBox1.Text
self._richTextBox1.Text = currentText + "\nModification Elements:\n" + "\n".join(lstElemNam)
self._ext_event.Raise()
def ButtonCancelClick(self, sender, e):
self._ext_event.Dispose()
self.Close()
try:
self._uiapp.ViewActivating -= self._delegateViewEvent
except:
self._uiapp.ViewActivating -= self.ViewEvent
try:
self._app.DocumentChanged -= self._delegateModifEvent
except:
self._app.DocumentChanged -= self.ModifEvent
self.Dispose()
class ModExternalEvent(IExternalEventHandler):
def Execute(self, _uiap):
_uidoc = _uiap.ActiveUIDocument
_doc = _uidoc.Document
_view = _doc.ActiveView
#processing
tx = Transaction(_doc)
tx.Start("MyEvent")
rvtcolor = Autodesk.Revit.DB.Color(255, 0, 0)
gSettings = OverrideGraphicSettings()
gSettings.SetProjectionFillColor(rvtcolor)
gSettings.SetProjectionLineColor(rvtcolor)
gSettings.SetCutLineColor(rvtcolor)
gSettings.SetCutFillColor(rvtcolor)
for elid in _uidoc.Selection.GetElementIds():
_view.SetElementOverrides(elid, gSettings)
tx.Commit()
def GetName(self):
return "Test External Event"
obj_handler = ModExternalEvent()
ext_event = ExternalEvent.Create(obj_handler)
objEvent = MainForm(ext_event, uiapp, app)
objEvent.Show()
OUT = 0
un autre Exemple avec seulement un tracking de modification d'éléments:
import sys
import clr
import System
from System import EventHandler, Uri
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Events import DocumentChangedEventArgs
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI import IExternalEventHandler, ExternalEvent
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
instdoc = DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *
class MainForm(Form):
def __init__(self, uiapp, app):
self._uiapp = uiapp
self._app = app
self.InitializeComponent()
def InitializeComponent(self):
self._buttonCancel = System.Windows.Forms.Button()
self._richTextBox1 = System.Windows.Forms.RichTextBox()
self._label1 = System.Windows.Forms.Label()
self.SuspendLayout()
self._app.DocumentChanged += EventHandler[DocumentChangedEventArgs](self.ModifEvent)
#
# buttonCancel
self._buttonCancel.Location = System.Drawing.Point(150, 550)
self._buttonCancel.Name = "buttonStop"
self._buttonCancel.Size = System.Drawing.Size(156, 37)
self._buttonCancel.TabIndex = 0
self._buttonCancel.Text = "Stop Loop Event"
self._buttonCancel.UseVisualStyleBackColor = True
self._buttonCancel.Click += self.ButtonCancelClick
#
# richTextBox1
self._richTextBox1.Location = System.Drawing.Point(30, 37)
self._richTextBox1.Name = "richTextBox1"
self._richTextBox1.Size = System.Drawing.Size(400, 500)
self._richTextBox1.TabIndex = 1
self._richTextBox1.Text = "Processing..."
#
# label1
self._label1.Location = System.Drawing.Point(30, 9)
self._label1.Name = "label1"
self._label1.Size = System.Drawing.Size(152, 25)
self._label1.TabIndex = 2
self._label1.Text = "Revit Events"
#
# MainForm
self.ClientSize = System.Drawing.Size(480, 600)
self.Controls.Add(self._label1)
self.Controls.Add(self._richTextBox1)
self.Controls.Add(self._buttonCancel)
self.Name = "MainForm"
self.Text = "UI_Event"
self.ResumeLayout(False)
def ModifEvent(self, sender, e):
#prevent if unregister event failed
if not self.Controls[0].IsDisposed:
lstElemNam = []
lstElemdIds = e.GetModifiedElementIds()
listTransactionName = e.GetTransactionNames()
for xId in lstElemdIds:
elem = doc.GetElement(xId)
if elem is not None or int(xId) != 1:
lstElemNam.append(elem.Name + "Id :"+ str(xId.IntegerValue))
if len(lstElemNam) > 0:
currentText = self._richTextBox1.Text
self._richTextBox1.Text = currentText + "\n\nLIST ELEMENTS:\n" + "\n".join(lstElemNam)
self._richTextBox1.Text += "\n\nTRANSACTION NAME :\n" + "\n".join(listTransactionName)
self._richTextBox1.Text += "\n\nUSER NAME : "+ self._app.Username
self._richTextBox1.Text += "\n###########################################"
self._ext_event.Raise()
def ButtonCancelClick(self, sender, e):
self.Close()
self._app.DocumentChanged -= EventHandler[DocumentChangedEventArgs](self.ModifEvent)
self.Dispose()
objEvent = MainForm(uiapp, app)
objEvent.Show()
OUT = 0
Note
L'exemple a été fait sous Revit 2019 et le code ne prends pas compte les divers changements d'API comme la classe DB.OverrideGraphicSettings
Bonne Année, prenez soin de vous et de vos proches
0 commentaires:
Enregistrer un commentaire