[Revit] Distribuer ses scripts et créer un installeur

OutilsPythonCVC

Grâce au livre électronique de Daren Thomas et à quelques recherches sur internet j’ai pu créer un installeur complet pour donner facilement des outils à des personnes intéressés mais qui n’ont jamais produit une ligne de code et/ou sans que Revit Python Shell (RPS) ait besoin d’être installé ! Voici les étapes du processus :

1- Créer ses scripts pour RPS. Dans cet exemple, je me servirais de mes petits scripts qui n’ont rien d’exceptionnel, pourraient grandement être améliorés et dont je me sers pourtant quasiment tous les jours quand je travaille sur mes modèles Revit (cf. articles précédents).

2- Créer un fichier Rps Addins tel que décrit au chapitre « Deploying RpsAddins ». Ce fichier est un xml qui indique le nombre de boutons à créer (PushButton) et leur script associé (src), le nom du ruban dans lequel ils se trouveront (RibbonPanel). Le chemin d’accès au script est toujours relatif à l’emplacement du fichier RpsAddin :

<?xml version="1.0" encoding="utf-8" ?>
<RpsAddin>
  <RibbonPanel text="PythonCVC.net">
    <!-- the script is always searched relative to the location of the RpsAddin xml file -->
    <PushButton text="Renommer la vue" src="Sources\renommer_vues.py"/>
    <PushButton text="Supprimer système" src="Sources\supprimer_système.py"/>
    <PushButton text="Rotation axe X" src="Sources\rotation_element.py"/>
    <PushButton text="Supprimer famille" src="Sources\supprimer_famille.py"/>
    <PushButton text="Supprimer type" src="Sources\supprimer_type.py"/>
  </RibbonPanel>
</RpsAddin>

3- Utiliser l’outil « Deploy RpsAddins » de RPS en pointant le fichier RpsAddins créé. Un message informe alors que que le déploiement est complété dans le dossier « Output_<Nom du xml> ».

4- Créer un fichier Revit .addin standard qui permet d’ajouter un addin à Revit. Le Champs <FullClassName> doit être le nom du fichier RpsAddins. Le chemin du champs <Assembly> est indiqué avec une variable « path » qui sera remplacer à l’installation par l’emplacement où l’utilisateur a choisi d’installer votre addin. Note importante : Ne copiez pas le champs <GUID> dans votre .addin, c’est un identifiant global unique (Global Unique Identifier) généré aléatoirement et comme son nom l’indique censé être unique. 2 addins avec le même GUID ne pourront pas être utilisés simultanément ou cela posera problème. Utilisez le générateur de GUID disponible dans Visual Studio, Inno Setup ou autre. Pour plus d’informations sur les champs disponibles/utiles (icônes etc…) consulter la documentation :

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<RevitAddIns>
  <AddIn Type="Application">
    <Name>Outils pythoncvc.net</Name>
    <Assembly>path\pythoncvc.dll</Assembly>
    <AddInId>C12476B2-1BA6-4A44-8646-0A6619070956</AddInId>
    <FullClassName>pythoncvc</FullClassName>
    <VendorId>REGISTER_YOUR_VENDOR_ID</VendorId>
    <VendorDescription>Python CVC, pythoncvc.net</VendorDescription>
    <VisibilityMode>NotVisibleInFamily</VisibilityMode>
    <LongDescription>
    Cet addin regroupe les outils développés par pythoncvc.net, plus d'informations sur le site.
    </LongDescription>
  </AddIn>
</RevitAddIns>

5- Créer un installeur exécutable (et dés-installeur). Ce point n’est pas encore couvert dans le livre, j’ai choisi « Inno Setup » qui est libre, gratuit et permet de réaliser facilement un installeur à l’aide d’un assistant. Pour plus de fonctionnalités, on peut modifier le script qui créé l’installeur, l’inconvénient est qu’il faut utiliser le langage Pascal (recherche google et stackoverflow sont nos amis !). L’assistant permet de générer la majorité du script, il suffit de lui renseigner le nom de l’application, version, fichiers à installer, dossier de destination par défaut, fichier de licence etc. A la fin, l’assistant vous demande si vous voulez lancez le script, dîtes non, il faut procéder à quelques modifications avant :

Le fichier .addin ne doit pas être installé au même endroit que le reste, il doit être installé (Vista/Windows 7) dans « %ProgramData%\Autodesk\Revit\Addins\2015\ » ou « %AppData%\Autodesk\Revit\Addins\2015\ » pour être lu par Revit. Il faut donc modifier le « DestDir » du fichier .addin en utilisant de préférence les variables environnement ({%ProgramData}).

Source: "C:\Program Files (x86)\pythoncvc.net\pythoncvc.addin"; DestDir: "{%ProgramData}\Autodesk\Revit\Addins\2015\"; Flags: ignoreversion

Grâce à un sujet sur stackoverflow et à la documentation d’InnoSetup, j’ai pu généré un code permettant de modifier le .addin à la fin de l’installation pour qu’il pointe vers le dossier d’installation choisi par l’utilisateur. Il cherche et remplace dans le .addin le mot « path » (cf. point 4) par le chemin choisi par l’utilisateur (constante {app}) :

[Code]
procedure Update();
var
C: AnsiString;
CU: String;
Path: String;
begin
        LoadStringFromFile(ExpandConstant('{%ProgramData}\Autodesk\Revit\Addins\2015\pythoncvc.addin'), C);
        CU := C;
        Path := ExpandConstant('{app}')
        StringChangeEx(CU, 'path', Path, True);
        C := CU;
        SaveStringToFile(ExpandConstant('{%ProgramData}\Autodesk\Revit\Addins\2015\pythoncvc.addin'), C, False);          
end;

function GetCustomSetupExitCode: Integer;
begin
  Update;
result := 0;
end;

Démonstration vidéo :

Vous pouvez retrouver l’ensemble des fichiers (sources et produits) ici : https://github.com/Nahouhak/pythoncvc.net/tree/master/Cr%C3%A9er%20un%20installeur

En espérant que cela aidera d’autres personnes à distribuer leurs pythonneries.

[Revit] Livre électronique sur le scripting avec RevitPythonShell

Daren Thomas est visiblement en train d’écrire un livre électronique intitulé « Scripting Autodesk Revit with RevitPythonShell ». Ce livre est un guide sur la création de script en python avec RevitPythonShell (RPS). Il regroupe plusieurs articles du blog de Daren Thomas avec des compléments appréciables. Il permet notamment de mieux comprendre :

  • certains aspects de RPS comme les variables prédéfinies (__revit__, __window__, __file__ etc.) qui m’ont posés pas mal de soucis dans mes tentatives pour réaliser une interface graphique utilisateur (GUI) avec Windows Presentation Foundation (WPF).
  • le StartupScript qui se lance au démarrage et permet par exemple de créer des rubans pour vos addins.
  • comment utiliser la fonction « Deploy RpsAddin » pour déployer facilement ses addins sur plusieurs machines et créer un installeur.

Dans les chapitres en cours de réflexion/construction, il y a notamment un chapitre sur la création de GUI que j’attends avec impatience.

On peut donc une fois de plus dire un grand merci à Daren Thomas pour son travail et on attend avec impatience les prochaines mises à jours.

Lien vers le livre électronique :  https://www.gitbook.com/book/daren-thomas/scripting-autodesk-revit-with-revitpythonshell/details

[Revit] Créer un tuyau d’un point A à un point B façon python

Plusieurs articles montrent comment créer un tuyau en C# :
http://pastebin.com/RZn1WnMW
http://thebuildingcoder.typepad.com/blog/2014/01/final-rolling-offset-using-pipecreate.html

Voici un code très court qui montre comment faire en python.

Il ne faut pas oublier d’ajouter la ligne suivante pour importer les fonctions liées aux tuyaux :

from Autodesk.Revit.DB.Plumbing import *

Pour créer un tube entre 0.0.0 et 10.0.0, le code est le suivant (on utilise le premier type de système et de tube qui nous tombe sous la main).

t = Transaction(doc, "Création d'un tuyau")
t.Start()
def pickobject():
	from Autodesk.Revit.UI.Selection import ObjectType
	__window__.Hide()
	picked = uidoc.Selection.PickObject(ObjectType.Element)
	__window__.Show()
	__window__.Topmost = True
	return picked
#Trouve un type de tuyau, un type de système et le niveau de la vue courante
idtypetuyau = FilteredElementCollector(doc).OfClass(PipeType).FirstElement().Id
idtypesystem = FilteredElementCollector(doc).OfClass(PipingSystemType).FirstElement().Id
idniveau = doc.ActiveView.GenLevel.Id
#Création du point de départ et d'arrivée du tuyau
p1 = XYZ(0, 0, 0)
p2 = XYZ(10, 0, 0)
#Création du tuyau
Pipe.Create(doc, idtypesystem, idtypetuyau, idniveau, p1, p2)
t.Commit()

[Revit] Rotation de famille sur l’axe X

L’outil rotation de Revit permet de faire une rotation sur l’axe z uniquement. Pour une rotation sur l’axe X, il faut aller en coupe et je n’aime pas devoir changer de vue pour une opération aussi simple. Voici un script pour effectuer une rotation sur l’axe X, on peut utiliser la même méthode sur l’axe Y :

t = Transaction(doc, "Rotation axe x")
t.Start()
point2 = XYZ(0,0,1)
for e in getselection():
	o = doc.GetElement(e).Location.Point
	z = XYZ(o.X + 1, o.Y, o.Z)
	axis = Line.CreateBound(o, z)
	ElementTransformUtils.RotateElement(doc,e,axis,pi/2)
t.Commit()

Voici une vidéo démo d’un application simple et utile :

[Revit] Supprimer un système MEP

Même principe que pour les familles, le code suivant supprime les systèmes des objets sélectionnés :

uidoc = __revit__.ActiveUIDocument
doc = __revit__.ActiveUIDocument.Document
getselection = uidoc.Selection.GetElementIds

t = Transaction(doc, "supprimer_système")
t.Start()
#Trouve l'Id des systèmes des objets sélectionnés et supprime ces systèmes
s = []
for e in getselection():    
    try:
        s.append(doc.GetElement(e).MEPSystem.Id)
    except:
        c = doc.GetElement(e).MEPModel.ConnectorManager.Connectors
        for i in c:
            if i.MEPSystem != None:
                id = Element.Id.GetValue(i.MEPSystem)
                print id
                s.append(id)                
for id in s:
    print id
    doc.Delete(id)
t.Commit()

Cette fonction est très utile pour gérer les systèmes. Il arrive souvent avec Revit que les systèmes ne fonctionnent pas comme on le voudrait et qu’il faille supprimer des systèmes polluant le projet. Supprimer un système est parfois le seul moyen de remettre les choses en ordre et il n’est pas pratique d’aller chercher le système dans le navigateur de système qui en contient parfois des centaines.

Vidéo démo (dsl pour les parasites, il faut que je trouve d’où ils viennent pour la prochaine) :