Add Altium Delphi scripts
[eda-utils.git] / scripts / altium / pcb-assembly-drawings.pas
diff --git a/scripts/altium/pcb-assembly-drawings.pas b/scripts/altium/pcb-assembly-drawings.pas
new file mode 100644 (file)
index 0000000..b5b3a45
--- /dev/null
@@ -0,0 +1,262 @@
+// Création des dessins d'assemblage sur les couches mécaniques 10 (TOP) et 11 (BOT)\r
+//\r
+// TODO:\r
+//   Afficher le nombre de composants total et celui qui est présentement traité (1/200)\r
+//   Gérer les composants avec des orientations non multiples de 90 deg.\r
+\r
+Const\r
+    MY_REF_SIZE_MILS  = 30;\r
+    MY_REF_WIDTH_MILS = 3;\r
+    \r
+    // La grosseur du texte en fonction de la taille du composant, jusqu´à cette limite.\r
+    TEXT_SIZE_MAX_MILS = 100;\r
+     \r
+    // Ratio de la longueur du texte du refdes par rapport à la longueur maximale permise par les dimensions du composant.\r
+    RATIO_MAXLEN_REFDES = 0.85;\r
+\r
+    // Ratio de la hauteur du texte du refdes par rapport à la hauteur maximale permise par les dimensions du composant.    \r
+    RATIO_MAXHEIGHT_REFDES = 0.65;\r
+    \r
+    // Ajustement empirique.\r
+    AJUSTEMENT_CENTRAGE = 0.90;\r
+    \r
+    TOP_ASSEMBLY_LAYER = eMechanical10;\r
+    BOT_ASSEMBLY_LAYER = eMechanical11;\r
+\r
+Procedure PCB_GenerateAssemblyDrawings;\r
+Var\r
+    Board     : IPCB_Board;\r
+    Comp      : IPCB_Component;\r
+    Iterator  : IPCB_BoardIterator;\r
+\r
+    strlen,   : Integer;\r
+    StrWidth  : TCoord;\r
+    StrHeight : TCoord;\r
+    OffsetX :   TCoord;\r
+    OffsetY :   TCoord;\r
+    MidX, MidY : Integer;\r
+    MaxLen     : Integer;\r
+    MaxHeight  : Integer;\r
+    TempSize : Integer;\r
+    \r
+    IsCircle : Boolean;\r
+    \r
+    DestLayer : TLayer;\r
+    TextObj : IPCB_Text;\r
+    \r
+    // Pour sauvegarder les valeurs du composant original.\r
+    OldCommentOn : Boolean;\r
+    OldCompRotation : Integer;\r
+    OldCompNameRotation : Integer;\r
+    \r
+    // Attributs du nouveau composant sur la couche d'assemblage\r
+    NewRotation  : Integer;\r
+    NewSize      : Integer;\r
+    \r
+Begin\r
+    Pcbserver.PreProcess;\r
+\r
+    Board := PCBServer.GetCurrentPCBBoard;\r
+    If Not Assigned(Board) Then\r
+    Begin\r
+        ShowMessage('The Current Document is not a Protel PCB Document.');\r
+        Exit;\r
+    End;\r
+    \r
+    // Efface les 2 couches d'assemblage\r
+    ClearAssemblyLayer(Board, TOP_ASSEMBLY_LAYER);\r
+    ClearAssemblyLayer(Board, BOT_ASSEMBLY_LAYER);\r
+    \r
+    // Setup Board iterator\r
+    Iterator        := Board.BoardIterator_Create; \r
+    Iterator.AddFilter_ObjectSet(MkSet(eComponentObject)); \r
+    //Iterator.AddFilter_LayerSet(MkSet(eBottomLayer));\r
+    Iterator.AddFilter_LayerSet(AllLayers); \r
+    Iterator.AddFilter_Method(eProcessAll);\r
+    \r
+    Comp := Iterator.FirstPCBObject;\r
+    While (Comp <> Nil) Do\r
+    Begin\r
+        IsCircle := False;\r
+        \r
+        // Check if Component Name property exists before extracting the text\r
+        If Comp.Name = Nil Then Exit;\r
+\r
+        // On ne modifie pas le numéro du PCB, qui est la référence du logo de compagnie\r
+        If CompareString(Comp.Pattern, 'LOGOCOMPANY', 7) Then\r
+        Begin\r
+           Comp := Iterator.NextPCBObject;\r
+           Continue;\r
+        End;\r
+\r
+        If CompareString(UpperCase(Comp.Pattern), 'MIRE', 4) Then\r
+        Begin\r
+           Comp := Iterator.NextPCBObject;\r
+           Continue;\r
+        End;\r
+\r
+        If CompareString(UpperCase(Comp.Pattern), 'CRACK', 5) Then\r
+        Begin\r
+           Comp := Iterator.NextPCBObject;\r
+           Continue;\r
+        End;\r
+\r
+        // On n´affiche pas les fiducials\r
+        If CompareString(UpperCase(Comp.Pattern), 'FIDG', 4) Then\r
+        Begin\r
+           Comp := Iterator.NextPCBObject;\r
+           Continue;\r
+        End;\r
+\r
+        // On n´affiche pas la légende des couches\r
+        If CompareString(UpperCase(Comp.Pattern), 'LAYERS', 6) Then\r
+        Begin\r
+           Comp := Iterator.NextPCBObject;\r
+           Continue;\r
+        End;\r
+\r
+        // Modify the component\r
+        PCBServer.SendMessageToRobots(Comp.I_ObjectAddress, c_Broadcast, PCBM_BeginModify , c_NoEventData);\r
+\r
+        // Sauvegarde valeurs originales\r
+        OldCommentOn := Comp.CommentOn;\r
+        OldCompRotation := Comp.Rotation;\r
+        OldCompNameRotation := Comp.Name.Rotation;\r
+\r
+        // Sauf pour les MH\r
+        if CompareString(Comp.Name.Text, 'MH', 2) Then\r
+            IsCircle := True;\r
+         if CompareString(Comp.Name.Text, 'TP', 2) Then\r
+            IsCircle := True;\r
+            \r
+        If IsCircle Then\r
+            Comp.Rotation := 0;\r
+\r
+        // Et on désactive temporairement les commentaires\r
+        Comp.CommentOn := False;\r
+        \r
+        // On fait une rotation de la référence selon l'orientation du composant\r
+        Case Comp.Rotation of\r
+            0, 180, 360 : Comp.Name.Rotation := 0;\r
+            90, 270 : Comp.Name.Rotation := 90;\r
+        End;\r
+\r
+        If Comp.Layer = eBottomLayer Then\r
+        Begin\r
+            Case Comp.Name.Rotation of\r
+                90   : Comp.Name.Rotation := 270;\r
+            End;\r
+        End;\r
+\r
+        FetchComponentMidPoints(Comp, MidX, MidY, MaxLen, MaxHeight);\r
+        \r
+        // string length * character_width <= MaxLen\r
+        // character_width = 2/3 * Size en mil.\r
+        //   Ex: Si le size est de 30 mils, la largeur est environ de 20 mils.\r
+        // -> Size = MaxLen / strlen * 3/2 \r
+        strlen := Length(Comp.Name.Text);\r
+\r
+        // Calcul de la grosseur de la référence selon la longueur disponible (bonding box).\r
+        TempSize := CoordToMils(MaxLen * RATIO_MAXLEN_REFDES) / strlen * 0.9;\r
+        if TempSize > TEXT_SIZE_MAX_MILS Then\r
+            TempSize := TEXT_SIZE_MAX_MILS;\r
+        \r
+        // Ajustement selon la hauteur disponible (bonding box).\r
+        If TempSize > (CoordToMils(MaxHeight) * RATIO_MAXHEIGHT_REFDES) Then\r
+            TempSize := CoordToMils(MaxHeight) * RATIO_MAXHEIGHT_REFDES;\r
+\r
+        // Adjust size according to available space\r
+        NewSize  := MilsToCoord(TempSize);\r
+        StrWidth := strlen * NewSize;\r
+        StrHeight:= NewSize;\r
+\r
+        If Comp.Layer = eTopLayer Then\r
+        Begin\r
+            DestLayer := TOP_ASSEMBLY_LAYER;\r
+            Case Comp.Name.Rotation of\r
+                0   :\r
+                    Begin\r
+                        OffsetX := -StrWidth  / 2;\r
+                        OffsetY := -StrHeight / 2;\r
+                    End;\r
+                90  :\r
+                    Begin\r
+                        OffsetX := StrHeight / 2;\r
+                        OffsetY := -StrWidth  / 2;\r
+                    End;\r
+            End;\r
+        End;\r
+        If Comp.Layer = eBottomLayer Then\r
+        Begin\r
+            DestLayer := BOT_ASSEMBLY_LAYER;\r
+            Case Comp.Name.Rotation of\r
+                0  :\r
+                    Begin\r
+                        OffsetX :=  StrWidth  / 2;\r
+                        OffsetY := -StrHeight / 2;\r
+                    End;\r
+                270 :\r
+                    Begin\r
+                        OffsetX := -StrHeight / 2;\r
+                        OffsetY := -StrWidth  / 2;\r
+                    End;\r
+            End;\r
+        End;\r
+        \r
+        // Ajustement empirique...    \r
+        Case Comp.Name.Rotation of\r
+            0   : OffsetX := OffsetX * AJUSTEMENT_CENTRAGE;\r
+            90  : OffsetY := OffsetY * AJUSTEMENT_CENTRAGE;\r
+            270 : OffsetY := OffsetY * AJUSTEMENT_CENTRAGE;\r
+        End;\r
+\r
+        // Sauvegarde nouvelles valeurs pour nouveau composant sur couche d'assemblage\r
+        NewRotation  := Comp.Name.Rotation;\r
+\r
+        // Restauration valeurs originales\r
+        Comp.CommentOn := OldCommentOn;\r
+        Comp.Rotation := OldCompRotation;\r
+        Comp.Name.Rotation := OldCompNameRotation;\r
+\r
+        PCBServer.SendMessageToRobots(Comp.I_ObjectAddress, c_Broadcast, PCBM_EndModify , c_NoEventData);\r
+        \r
+        If IsCircle Then\r
+            // Crée un cercle représentant le composant\r
+            CreateBondingcircle(Board, DestLayer, MidX, MidY, MaxLen / 2)\r
+        Else\r
+            // Crée une boite représentant le composant\r
+            CreateBondingBox(Board, DestLayer);\r
+        \r
+        //Create a first text object non True Type font.\r
+        TextObj := PCBServer.PCBObjectFactory(eTextObject, eNoDimension, eCreate_Default);\r
+\r
+        // notify that the pcb object is going to be modified\r
+        PCBServer.SendMessageToRobots(TextObj.I_ObjectAddress ,c_Broadcast, PCBM_BeginModify , c_NoEventData);\r
+\r
+        TextObj.Layer     := DestLayer;\r
+        TextObj.XLocation := MidX + OffsetX;\r
+        TextObj.YLocation := MidY + OffsetY;\r
+        TextObj.Rotation  := NewRotation;\r
+        TextObj.Text      := Comp.Name.Text;\r
+        TextObj.Size  := NewSize;\r
+        TextObj.Width := MilsToCoord(MY_REF_WIDTH_MILS);\r
+        TextObj.UseTTFonts := False; \r
+        TextObj.Italic := False; \r
+        TextObj.Bold := False; \r
+        TextObj.FontName := 'Default';\r
+        If Comp.Layer = eBottomLayer Then\r
+            TextObj.MirrorFlag := True;\r
+\r
+        Board.AddPCBObject(TextObj);\r
+\r
+        // notify that the pcb object has been modified\r
+        PCBServer.SendMessageToRobots(TextObj.I_ObjectAddress, c_Broadcast, PCBM_EndModify         , c_NoEventData);\r
+       \r
+        Comp := Iterator.NextPCBObject;\r
+    End;\r
+    \r
+    Board.BoardIterator_Destroy(Iterator);\r
+    \r
+    Pcbserver.PostProcess;\r
+    Client.SendMessage('PCB:Zoom', 'Action=Redraw', 255, Client.CurrentView);\r
+End;\r