Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Forum destiné aux questions et discussions en français
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
User avatar
-alex-
Veteran
Posts: 1856
Joined: Wed Feb 13, 2019 9:42 pm
Location: France

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by -alex- »

2cv001 wrote: Thu Jan 05, 2023 3:58 pm Sinon, je ne suis pas sûr de comprendre ta première phrase : "donne quand même tes infos FreeCAD. ca a le mérite d’être précis."
C'est le fait d'jouter une capture écran de la version "normale". Je viens de le faire. C'est bien ce que tu suggérais ?
David suggère juste de copier-coller les info FreeCAD suivant la procédure d'aide ;-)
https://forum.freecadweb.org/viewtopic. ... 64#p423310
Image
User avatar
2cv001
Posts: 484
Joined: Wed Jan 01, 2020 9:30 am

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by 2cv001 »

Avec traduction en anglais des commentaires (mais pas encore de ce qui s'affiche à l'écran), cela donnerait cela :

Code: Select all

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Macro that creates an "stl" file with perfect rounding
= without visible facets.
It also allows to launch programs of your choice
For example to automate the FreeCAD -> Slicer -> printing line

Principle of smoothing : it modifies the deviation property of the solids before
generation of the stl and then replace the old values
At the end, it proposes to launch the stl file which will open for example under
cura if the stl extension has been associated with cura in your operating system.

Launching other programs or commands :
You can ask it to chain any program or command that you might  
type in a terminal. 
To do this, you must change what is in the
"parameters that can be changed" section. 

Examples of applications: 
- Turn on the printer and the light (requires for example a controlled socket)
- Connect octoprint to the printer
- Start the tray preheating
- Save your FreeCAD and stl file
....


Tested on windows and Linux
"""
import FreeCAD as App
import Mesh
from PySide2 import QtCore, QtWidgets
import os, sys, subprocess
import time
import FreeCADGui as Gui

#================================
# Parameters that can be changed
#================================

# Smoothing management
#--------------------

# deviation : default value that will be displayed in the dialog box. 
# 0.5 is the default value in FreeCad, 0.05 allows a stronger smoothing.
# 0.01 is perfect from a smoothing point of view. 
# The lower the value, the better the quality, 
# but the larger the size of the stl file
# the value must be between 0 and 1
deviation=0.01 
doitLancerFichier=True # if True, it will be proposed to launch the stl file.
                                 # otherwise put False

# Automatic program launch,
# Automation of the production line
#------------------------------------------

delaiMax=10 # if the user enters a delay greater than this value,
                   # it will be reduced to delaiMax

#To launch programs of your choice
    #Typically for example a home automation program, 
    #turn on your printer or/and a light etc.
    #Use the following syntax by adding a line below, in commands=[....:
#  [ ['command to execute', 'param 1', param 2, ] ,'.extention','question to ask', waiting time],
#
# 'command to execute' : the command you want to execute. 
# 'param 1, param 2,...' : if your program needs parameters. 
# These parameters will be taken into account only if extention=''.
#
# 'extention': if not empty then the first parameter will be replaced by the name of 
# your FreeCAD file but with this extension.
# 'question to ask': the question to display in the dialog box
# time_wait : optional : nb of seconds to wait after execution
# allows for example to wait for the printer to start before asking it  to heat the plate

# Note the double \ in place of \ (because the special characters
# must be preceded by an \ in python). ditto for the apostrophe for example
# the lines in question are to be inserted further down after commands=[...
#
# Examples of possible launches:

"""
[ ['calc.exe'                                         ] ,''    ,'Launch the calculator ?'],
[ ['C:\\WINDOWS\\system32\\mspaint.exe','dessin.jpg'  ] ,''    ,'Launch  Paint ?'          ],
[ ['C:\\Program Files\\Ultimaker Cura 4.8.0\\Cura.exe'] ,'.stl','Launch  Cura ?'           ],
[ ['curl','http://pidomotique/connecte.php'           ] , ''   ,'Connect the printer ?'],
[ ['C:\\Program Files\\Mozilla Firefox\\firefox.exe','https://octopi.local'],'','Launch Octoprint ?'],
 On linux:
[ [   'firefox','https://octopi.local'                ] , ''   ,'Launch Octoprint ?'      ], 

Example of printer control via octoprint (if you have it...):
   temperature setting of the plate
- Replace the XXX after X-Api-Key: by your API key
(found in the octoprint parameters)
- Replace http://octopi.local by the url with which you access octoprint
- Change the value 050 in "M140 S050". S050 indicates that you need to heat to 50°.
     if you want 60°, replace S050 by S060
- 6 lines to copy after having adapted it:
  [
      [  'curl','-H', 'Content-Type: application/json','-H', 'X-Api-Key: XXXXXXXXXXXXXXXXXXXXX', '-X', 'POST',
            '-d {"command":"M140 S050"}','http://octopi.local/api/printer/command'
      ]
            , '','Warm up the printer plate ?'
  ],

"""


commandes=[
# insert your lines here.
#  [ ['calc.exe'                                         ] ,''    ,'Lancer la calculatrice ?',2],
#  [ ['C:\\Program Files\\Ultimaker Cura 5.2.1\\Ultimaker-Cura.exe'] ,'.stl','Lancer Cura ?'           ],
#  [  ['curl','http://pidomotique/connecte.php'              ] , ''   ,'Allumer et connecter l\'imprimante ?',4],
  [  ['curl', 'https://pijeedom/core/api/jeeApi.php?apikey=xxxxxxxxxxxxxxxx&type=cmd&id=4042','--insecure' ] , ''   ,'Allumer et connecter l\'imprimante ?',10],
  [  ['curl','https://pijeedom/core/api/jeeApi.php?apikey=xxxxxxxxxxxxxxx&type=cmd&id=4048','--insecure'  ] , ''   ,'Chauffer le bed ?'],
  [ ['C:\\Program Files\\Mozilla Firefox\\firefox.exe','https://octopi'],'','Lancer Octoprint ?'],

                    ]


#===============
#Initialisations
#===============
dictionnaireOrigineDeviation={}
mw = Gui.getMainWindow()
indiceCommandeEtParam=0
indiceExtFileNameParamCommandeALancer=1
indiceTextAutreCommandeALancer=2
indiceDelai=3

# UI Class definitions
class BoiteDialogueSTLGuiClass(QtWidgets.QDialog):

    def  __init__(self, parent=None):
        super(BoiteDialogueSTLGuiClass, self).__init__(parent)
        self.initUI()

    def initUI(self):
        self.tabCheckboxTextCommandes=[] # table of checkbox commands to run
        self.setGeometry( 250, 250, 400, 150)
        self.setWindowTitle("Export et lancement de programmes")
        lay = QtWidgets.QGridLayout(self) 

        # checkboxs
        self.checkboxGenererSTL = QtWidgets.QCheckBox("Générer le STL", self)
        self.checkboxGenererSTL.setCheckState(QtCore.Qt.Checked)
        lay.addWidget(self.checkboxGenererSTL, 0, 0) 
        if doitLancerFichier :
            self.checkboxLancerSTL = QtWidgets.QCheckBox("Lancer le slicer", self)
            self.checkboxLancerSTL.setCheckState(QtCore.Qt.Checked)
            lay.addWidget(self.checkboxLancerSTL, 2, 0) 

        for posLigne, cmd in enumerate(commandes, start=3):
           textCommande=cmd[indiceTextAutreCommandeALancer]
           self.checkboxTextCommande = QtWidgets.QCheckBox(textCommande, self)
           # storing this checkbox in a table :
           self.tabCheckboxTextCommandes.append(self.checkboxTextCommande)
           self.checkboxTextCommande.setCheckState(QtCore.Qt.Checked)
           lay.addWidget(self.checkboxTextCommande, posLigne, 0) 

        # numeric input field
        self.label2 = QtWidgets.QLabel('Précision (param deviation) \nentre 0.01 et 1\n'+
             '0.01 pour une grande qualité', self)
        lay.addWidget(self.label2, 0, 1) 

        self.precision = QtWidgets.QDoubleSpinBox(self)
        self.precision.setValue(deviation)
        self.precision.setRange(0.01,1)
        self.precision.setSingleStep(0.01)
        self.precision.setToolTip('Plus le chiffre est grand, plus la taille ' +
            'du fichier est grande \net meilleur est la précision.\n'+
            'Voir le paramètre deviation dans FreeCAD')
        lay.addWidget(self.precision, 0, 2) 

        butBox = QtWidgets.QDialogButtonBox(self)
        butBox.setOrientation(QtCore.Qt.Horizontal)
        butBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
        lay.addWidget(butBox) 
        butBox.accepted.connect(self.accept)
        butBox.rejected.connect(self.reject)

        self.setLayout(lay)
    

#===============
#functions
#===============
def octopi(api,commande,urlOctopi,apiKey) :
    """
    Function that returns the parameter to pass to subprocess.Popen if you want to run an
    an octopi API. Not used here. But for memory purposes and a future evolution

    Arguments : 
        api : the api to run ex: '/api/printer/command'
        commande : the command of the API in question ex: '{"command": "M140 S050"}'
        urlOctoprint : the url of your octopi ex : 'https://octopi.local'
        apiKey : the API key you find in setting/API of octoprint
    Returns :

   Example
       API running a gcode. Here the heating of the printer plate
       subprocess.Popen(
                          octopi(
                                '/api/printer/command',
                                '{"command":"M140 S050"}',
                                'https://octopi.local',
                                'XXXXKEYXAPIXXXXXXXX'))
                 ,close_fds=True)
    """
    commandeCurl=[
    'curl','-H', 'Content-Type: application/json','-H',
         'X-Api-Key: '+apiKey,
         '-X', 'POST',
        '-d '+commande,urlOctopi+api
    ]
    return commandeCurl


def nameFileStl(dictionnaireOrigineDeviation,mw=Gui.getMainWindow()):
    """
    Function that determines and returns the file name including path
    where the stl will be saved
    The FreeCAD document containing the dictionary objects must be 
    opened and saved

    Arguments : 
        dictionaryOrigineDeviation (dictionary) : 
            a dictionary whose keys are FreeCAD solids. 
            the filename will be obtained from the filename of the 
            of the document containing the first object (solid) of this
            dictionary

    Returns :
        '' if the document does not exist,
        otherwise the name of the file where the stl will be saved

    Example
    """

    doc=list(dictionnaireOrigineDeviation.keys())[0].Document
    if doc is None:
        QtWidgets.QMessageBox.information(mw,'Attention',\
            "Vous n'avez pas de document ouvert")
        return ''
    if doc.FileName=='':
        QtWidgets.QMessageBox.information(mw,
             'Attention','Sauvez votre document avant de relancer la commande') 
        return ''
    return(os.path.splitext(doc.FileName)[0]+'.stl')

def memoriseObjEtDeviation(selection,deviationImpose):
    """
    Memorises the solids that are contained in selection and their
    deviation property and replaces it with the value 
    of deviationImpose
    It imposes a subsequent recompute by a touch.
    Recompute() must eventually be run after

    Arguments :
        selection: a selection of objects
deviationImpose (float): value that we want to impose to deviation.

    Returns: 
        a dictionary containing the object in key and the deviation in value
        Returns {} if there is no suitable object in the selection

    Example:
        memoriseObjEtDeviation(Gui.Selection.getSelection(),deviation)
    """
    dicoObjDeviation={}
    for objData in selection :
        if objData.isDerivedFrom('Part::Feature') \
          and not objData.isDerivedFrom('PartDesign::Feature')\
          and not objData.isDerivedFrom('Part::Part2DObject'):
            dicoObjDeviation[objData]=objData.ViewObject.Deviation
            objData.ViewObject.Deviation=deviationImpose 
           # pour imposer un recompute même si la déviation est plus petite
           # qu'avant :
            objData.touch()
            for o in objData.ViewObject.claimChildren():
                    o.touch()
    return dicoObjDeviation

def restitueDeviation(dicoOrigineDeviation):
    """
 Function that replaces the deviation property in the objects
    It imposes a recompute by a touch. recompute() must be
    run after

    Arguments:
        dicoOrigineDeviation a dictionary containing the object in key 
        and the value to be imposed in the deviation property of the object
        in value

    Returns: Does not return anything

    Example:
        restitueDeviation(dicoOrigineDeviation)

    """
    for ob2 in dicoOrigineDeviation:
        ob2.ViewObject.Deviation=dicoOrigineDeviation[ob2]
        # to impose a recompute even if the deviation is smaller
        # than before:
        ob2.touch()
        for o in ob2.ViewObject.claimChildren():
            o.touch()

def openFile(fileName):
    """
 function that launches a file depending on the operating system
    checked for now only under windows

    Arguments:
        fileName (string) the name of the file to run

    Returns
        Does not return anything

    Example: 
        openFile(unfichier.stl)
        openFile(calc.exe)
    """
    if sys.platform == "win32":
        os.startfile(fileName)
    else:
        opener ="open" if sys.platform == "darwin" else "xdg-open"
        subprocess.Popen([opener, fileName],close_fds=True) 

def recalcul(dicoObjs):
    """
    launches a recompute for each Document of the dico objects
    only if it has not already been done
    Arguments:
        dicoObjs a dictionary containing the object in key 

    Returns
        Does not return anything

    Example:
        recalcul(dicoMesObjets)
    """
    docDejaRecalcul=[]
    for obj in dicoObjs:
        if obj.Document not in docDejaRecalcul:
            obj.Document.recompute()
            docDejaRecalcul.append(obj.Document)

def lanceCommmandes(commandesAlancer,fileStlName,formBoiteDialogueSTL):
    """
    launch the orders
    Arguments:
        commandesAlancer in the form of an array of arrays
        [ ['command to execute', 'param 1', param 2, ] ,'.extention','question to ask',delay ],
          ['command to execute', 'param 1', param 2, ] ,'.extention','question to ask',delay ],
          ...
        ]
         'command to execute' : the command you want to execute. 
         For example 'myProgram.exe' if need, put also its path. 
         param 1, param2... ' : if your program needs parameters. 
            Will only be taken into account if extention=''.
         'extention': if not empty, parameter param 1 will be the name of your
              FreeCAD file but with your extension :
         question to ask': the question to display in the dialog box
         delay: waiting time in seconds before going to the next command.

    Returns
         Do not return anything

    Example:
        lanceCommmandes(commandes,fileStlName,formBoiteDialogueSTL) # lance les commandes que l'on a décrites dans commandes
    """

    for tbktc in formBoiteDialogueSTL.tabCheckboxTextCommandes :
        if tbktc.isChecked() :
            i= formBoiteDialogueSTL.tabCheckboxTextCommandes.index(tbktc)
            commande=commandesAlancer[i]
            commandeEtParam=commande[indiceCommandeEtParam]
            extFileNameParamCommandeALancer=commande[indiceExtFileNameParamCommandeALancer]
            textAutreCommandeALancer=commande[indiceTextAutreCommandeALancer]
            delai=0
            try :
               if commande[indiceDelai:indiceDelai+1]!=[] : #si l'utilisateur a rentré un délai
                  delai=commande[indiceDelai]
            except :
               print ('Délai non pris en compte car valeur numérique non valide'+
                      'pour la commande '+ textAutreCommandeALancer)
            if delai > delaiMax :
                delai=delaiMax

            if extFileNameParamCommandeALancer!='':     
                if commandeEtParam[2:3]==[]  : # Il n'y a aucun paramètre.
                   # On ajoute un paramètre pour y mettre notre nom de fichier
                   # avec notre extension.
                   commandeEtParam.append('')
                commandeEtParam[1]=   os.path.splitext(fileStlName)[0]+  extFileNameParamCommandeALancer
            subprocess.Popen(commandeEtParam,close_fds=True)
            print(commandeEtParam)
            time.sleep(delai)# Pause de durée delai secondes   


def run(objs=Gui.Selection.getSelection(), dev=deviation):
    """
    main function
    Arguments:
        doc: the active document
        objs : the objects that have been selected beforehand
        dev : the value of the deviation property which will be 
              imposed before the generation of the stl

    Returns
        Returns nothing

    Example:
        run()
    """

   #check if at least one solid (body and similar) has been selected
    nbBody=0
    for objData in objs :
        if objData.isDerivedFrom('Part::Feature') \
          and not objData.isDerivedFrom('PartDesign::Feature')\
          and not objData.isDerivedFrom('Part::Part2DObject'):
          nbBody=nbBody+1

    if nbBody==0: # # if we haven't found any solids, but we have to have an active one
         try: 
            objs=[]
            objs.append(Gui.ActiveDocument.ActiveView.getActiveObject('pdbody'))
            response=QtWidgets.QMessageBox.information(mw, 'Attention',\
            '-Vous n\'avez pas sélectionné de solide. Sélection automatique du solide '+objs[0].Label +
            ' par le programme..\n-Si non satisfaisant, avant de lancer la macro, sélectionnez un ou plusieurs solides avant de lancer la macro', 
                  QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel )
            if response==QtWidgets.QMessageBox.Cancel :
              return
         except :
            QtWidgets.QMessageBox.information(mw, 'Attention',\
            '--Sélectionnez un ou plusieurs solides avant de lancer la macro')
            return
    
# Dialog box of what we want to do
    formBoiteDialogueSTL=BoiteDialogueSTLGuiClass(mw)
    if not formBoiteDialogueSTL.exec_() : 
        return
    dev=formBoiteDialogueSTL.precision.value()
    # we memorize the selected solids and their deviation,
    # we make a touch() of their child to be taken into account in recompute :
    dictionnaireOrigineDeviation=memoriseObjEtDeviation(objs,dev)
    if len(dictionnaireOrigineDeviation)==0: # si on a trouvé aucun solide
        QtWidgets.QMessageBox.information(mw, 'Attention',\
            '-Sélectionnez un ou plusieurs solides avant de lancer la macro')
        return
    # we get the name of the file where we have to save the stl
    fileStlName=nameFileStl(dictionnaireOrigineDeviation)
    if fileStlName == '' :
        return
    #The solids in dictionaryOriginDeviation are passed as parameters
    if formBoiteDialogueSTL.checkboxGenererSTL.isChecked():
       Mesh.export(list(dictionnaireOrigineDeviation.keys()), fileStlName) 
       print('Export fait')
    # restitution of the original property deviation for all solids :
    restitueDeviation(dictionnaireOrigineDeviation)
    recalcul(dictionnaireOrigineDeviation)

    if formBoiteDialogueSTL.checkboxLancerSTL.isChecked():
            #runs for example cura if cura has been associated with *.stl files
            openFile(fileStlName)

    lanceCommmandes(commandes,fileStlName,formBoiteDialogueSTL)
            # runs the commands described in commands


if __name__ == '__main__':
    run()


Macro Sketch Constraint From Spreadsheet :
https://wiki.freecad.org/Macro_Sketch_C ... adsheet/fr
User avatar
2cv001
Posts: 484
Joined: Wed Jan 01, 2020 9:30 am

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by 2cv001 »

david69 wrote: Thu Jan 05, 2023 9:03 am c'est quoi tes info de FreeCAD? ca ressemble a de la 0.19 avec ces traductions d'ateliers qui ont ete rectifiees avec la 0.20.
OS: Windows 10 Version 2009
Word size of FreeCAD: 64-bit
Version: 2022.1128.26244 +5318 (Git)
Build type: Release
Branch: LinkDaily
Hash: d45d221edcc7a757eb4e4eb638da0db5ed2759aa
Python version: 3.8.10
Qt version: 5.15.2
Coin version: 4.0.1
OCC version: 7.6.2
Locale: French/France (fr_FR)
Macro Sketch Constraint From Spreadsheet :
https://wiki.freecad.org/Macro_Sketch_C ... adsheet/fr
User avatar
2cv001
Posts: 484
Joined: Wed Jan 01, 2020 9:30 am

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by 2cv001 »

A noter une nouvelle version qui permet de ne pas avoir sélectionner de body.
Si c'est la cas, elle prend en compte le body (ou assimilé) actif.
On est quand même prévenu par cette fenêtre
Capture1.PNG
Capture1.PNG (27.38 KiB) Viewed 723 times
Je n'ai pas encore mis le code source en premier message, mais le message qui donne au-dessus une traduction des commentaires en anglais contient cette fonctionnalité.
Macro Sketch Constraint From Spreadsheet :
https://wiki.freecad.org/Macro_Sketch_C ... adsheet/fr
User avatar
2cv001
Posts: 484
Joined: Wed Jan 01, 2020 9:30 am

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by 2cv001 »

david69 wrote: Thu Jan 05, 2023 12:55 pm ....

au passage, dans ton code, tu as commente en francais, est ce que tu prevois de partager ta macro avec les non francophones? si oui, ca serait peut etre mieux de traduire en anglais. qu'en penses tu?
Là, comme tu as pu voir dans un message précédent, j'ai fait une tentative de traduction des commentaires, mais pour ce qui est des boites de dialogues (par exemple le message d’avertissement comme quoi on a pas fait de sélection), comment les rendre multi languages. Il y a des consignes là-dessus ?
Macro Sketch Constraint From Spreadsheet :
https://wiki.freecad.org/Macro_Sketch_C ... adsheet/fr
User avatar
flachyjoe
Veteran
Posts: 1869
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by flachyjoe »

Salut,
Merci de conserver la version française des commentaires dans la macro lors de son partage.

Il serait bon de toujours commenter le code dans sa langue maternelle puis de commenter/traduire en anglais.
Un effort important est fait pour que la documentation soit accessible dans toutes les langues du wiki, il n'y a aucune raison de ne pas appliquer le même principe au code.
- Flachy Joe -
Image
david69
Veteran
Posts: 1773
Joined: Wed Jan 01, 2014 7:48 pm

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by david69 »

2cv001 wrote: Thu Jan 05, 2023 5:30 pm OS: Windows 10 Version 2009
Word size of FreeCAD: 64-bit
Version: 2022.1128.26244 +5318 (Git)
Build type: Release
Branch: LinkDaily
Hash: d45d221edcc7a757eb4e4eb638da0db5ed2759aa
Python version: 3.8.10
Qt version: 5.15.2
Coin version: 4.0.1
OCC version: 7.6.2
Locale: French/France (fr_FR)
oui, merci. je comprends mieux ainsi et ce qui explique notre ecart et pour les autres si jamais il y a un comportement different avec ta macro.

la aussi merci pour l'anglais. disons que si le Nepalais de service causant un peu l'anglais veut la prendre et la personnaliser, avec cela il saura quoi faire.

Edit: boite de dialogue en francais, je n'avais pas pense a cela dans ma suggestion mais plutot les commentaires du code. boites de dialogue, bah je n'ai pas trop vue de de boite de dialogue en russe ou italien ou allemand jusqu'a present. a toi de voir.
User avatar
2cv001
Posts: 484
Joined: Wed Jan 01, 2020 9:30 am

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by 2cv001 »

flachyjoe wrote: Thu Jan 05, 2023 9:02 pm Salut,
Merci de conserver la version française des commentaires dans la macro lors de son partage.

Il serait bon de toujours commenter le code dans sa langue maternelle puis de commenter/traduire en anglais.
Un effort important est fait pour que la documentation soit accessible dans toutes les langues du wiki, il n'y a aucune raison de ne pas appliquer le même principe au code.
J'avoue ne pas être sûr de comprendre.
Tu préconises de laisser en français mais d'avoir aussi une version en Anglais ? Pas facile de maintenir deux versions différentes.
En général, les macros sont commentés en anglais non ?
Macro Sketch Constraint From Spreadsheet :
https://wiki.freecad.org/Macro_Sketch_C ... adsheet/fr
User avatar
2cv001
Posts: 484
Joined: Wed Jan 01, 2020 9:30 am

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by 2cv001 »

Question bête,
Une fois résolu ce problème de traduction,
Quelle démarche à suivre pour mettre une macro à disposition ?
J'ai cru voir qu'il faut avoir un wiki. Bonne idée, un tuto pour savoir comment s'y prendre ?
Macro Sketch Constraint From Spreadsheet :
https://wiki.freecad.org/Macro_Sketch_C ... adsheet/fr
User avatar
-alex-
Veteran
Posts: 1856
Joined: Wed Feb 13, 2019 9:42 pm
Location: France

Re: Macro pour obtenir un stl avec des arrondis parfaits et piloter octoprint

Post by -alex- »

2cv001 wrote: Fri Jan 06, 2023 7:19 am Quelle démarche à suivre pour mettre une macro à disposition ?
J'ai cru voir qu'il faut avoir un wiki. Bonne idée, un tuto pour savoir comment s'y prendre ?
https://forum.freecadweb.org/viewtopic.php?f=21&t=6830
Ensuite tu peux ajouter ta macro à la liste des macro Macros_recipes, @mario52 pourrait peut-être te conseiller au besoin, il en a déjà fait tellement :D
Post Reply