Polylines don't connect to desired point

Polylines don't connect to desired point

imegusta02
Participant Participant
1,717 Views
16 Replies
Message 1 of 17

Polylines don't connect to desired point

imegusta02
Participant
Participant

I've been working on a script to connect a series of LEDs to each other utilizing a BOTTOM and TOP point parameter, the code takes the correct TOP point and draws a polyline except it doesn't connect to the BOTTOM point of the block above it and I can't instantly see what I'm doing wrong

0 Likes
Accepted solutions (2)
1,718 Views
16 Replies
Replies (16)
Message 2 of 17

EnM4st3r
Advocate
Advocate

you should also post a sample dwg 

0 Likes
Message 3 of 17

imegusta02
Participant
Participant

oh yeah thanks, here it is

0 Likes
Message 4 of 17

john.uhden
Mentor
Mentor

@imegusta02 ,

When you say "above" do you mean in the Y direction or the Z direction?

John F. Uhden

0 Likes
Message 5 of 17

imegusta02
Participant
Participant
In the Y direction
0 Likes
Message 6 of 17

daniel_cadext
Advisor
Advisor

Build a list of lists of the positions, mapped by X, sorted by Y, then connect the dots

Sorry lisp is above my pay grade, I hope this will illustrate the concept

 

from pyrx_imp import Rx, Ge, Gi, Db, Ap, Ed
import traceback

def PyRxCmd_doit():
    try:
        xs = {}
        ss = Ed.Editor.select([(2, "LED_PATH_C_V2")])
        
        # create a map of positions with x as the key [x]:[pos1,pos2,pos3...]
        for pos in [Db.BlockReference(id).position() for id in ss[1].objectIds()]:
            xs.setdefault(int(pos.x), []).append(pos)
            
        # sort then draw the lines 
        for it in xs.values():
            it.sort(key=lambda p: p.y)
            for idx in range(1, len(it)):
                Ed.Core.grDraw(it[idx - 1], it[idx], idx, 0)
                
    except Exception as err:
        traceback.print_exception(err)

LED.png

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
Message 7 of 17

Moshe-A
Mentor
Mentor

@imegusta02  hi,

 

Attached ConnectStackedBlocks command to do want you after.

it start by asking [Select object(s)], select all your blocks (only 1 group of array). the block name does not

matter as long as it is dynamic and it has the TOP\BOTTOM dynamic properties.

 

The array must be rectangle align to WCS.

 

The blocks in a row must be aligned (same y) but small Y_FAZZ (default = 0.02) is allowed to consider them on the same row. the same rule is applied between 2 close blocks: Bottom and Top. if x value of both is equal or within X_FAZZ (default = 0.02), they consider one above other.

 

X_FAZZ and Y_FAZZ are 2 constant variables define at the start of the command. if you need a different fuzz, you are invite to reset them.

 

line 215 => (setq X_FAZZ 1e-2 Y_FAZZ 1e-2) ; const

1e-2 is equal to 0.02 😀

 

if the array contains blocks that are not dynamic and\or does not have the TOP\BOTTOM properties they are skipped.

if the program cannot find the matched block (same x) the block below is skipped.

if the array has empty space (missing block) the block bellow is skipped.

 

i use (entmake) function to draw the lines to achieve maximum drawing speed.

 

In your sample dwg, the first block (the bottom left) has no dynamic properties - is this ok?

 

Special thanks to Gils from France and Lee Mac for providing us (the world) these beautiful functions without them this program would not be made.

 

enjoy

Moshe

 

(vl-load-com) ; load activex suppport

;; TransNested (gile)
;; Translates a point coordinates from WCS or UCS to RCS -coordinates system of a
;; reference (xref or block) whatever its nested level-
;;
;; Arguments
;; pt : the point to translate
;; rlst : the parents entities list from the deepest nested to the one inserted in
;;        current space -same as (last (nentsel)) or (last (nentselp))
;; from to : as with trans function: 0 for WCS, 1 for current UCS, 2 for RCS

(defun TransNested (pt rlst from to)
  (setq mat '((1 0 0) (0 1 0) (0 0 1)))
  (and (= 1 from) (setq pt (trans pt 1 0)))
  (and (= 2 to) (setq rlst (reverse rlst)))
  (and (or (= 2 from) (= 2 to))
       (while rlst
	 (setq geom (if	(= 2 to)
		      (RevRefGeom (car rlst))
		      (RefGeom (car rlst))
		    )
	       rlst (cdr rlst)
	       pt   (mapcar '+ (mxv (car geom) pt) (cadr geom))
	 )
       )
  )
  (if (= 1 to)
    (trans pt 0 1)
    pt
  )
)

;; RefGeom (gile)
;; Returns a list which first item is a 3x3 transformation matrix (rotation,
;; scales, normal) and second item the object insertion point in its parent
;; (xref, bloc or space)
;;
;; Argument : an ename

(defun RefGeom (ename / elst ang norm mat)
  (setq	elst (entget ename)
	ang  (cdr (assoc 50 elst))
	norm (cdr (assoc 210 elst))
  )
  (list
    (setq mat
	   (mxm
	     (mapcar (function (lambda (v) (trans v 0 norm T)))
		     '((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
	     )
	     (mxm
	       (list (list (cos ang) (- (sin ang)) 0.0)
		     (list (sin ang) (cos ang) 0.0)
		     '(0.0 0.0 1.0)
	       )
	       (list (list (cdr (assoc 41 elst)) 0.0 0.0)
		     (list 0.0 (cdr (assoc 42 elst)) 0.0)
		     (list 0.0 0.0 (cdr (assoc 43 elst)))
	       )
	     )
	   )
    )
    (mapcar
      '-
      (trans (cdr (assoc 10 elst)) norm 0)
      (mxv mat
	   (cdr (assoc 10 (tblsearch "BLOCK" (cdr (assoc 2 elst)))))
      )
    )
  )
)

;; RevRefGeom (gile)
;; RefGeom inverse function

(defun RevRefGeom (ename / entData ang norm mat)
  (setq	entData	(entget ename)
	ang	(- (cdr (assoc 50 entData)))
	norm	(cdr (assoc 210 entData))
  )
  (list
    (setq mat
	   (mxm
	     (list (list (/ 1 (cdr (assoc 41 entData))) 0.0 0.0)
		   (list 0.0 (/ 1 (cdr (assoc 42 entData))) 0.0)
		   (list 0.0 0.0 (/ 1 (cdr (assoc 43 entData))))
	     )
	     (mxm
	       (list (list (cos ang) (- (sin ang)) 0.0)
		     (list (sin ang) (cos ang) 0.0)
		     '(0.0 0.0 1.0)
	       )
	       (mapcar (function (lambda (v) (trans v norm 0 T)))
		       '((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
	       )
	     )
	   )
    )
    (mapcar '-
	    (cdr (assoc 10 (tblsearch "BLOCK" (cdr (assoc 2 entData)))))
	    (mxv mat (trans (cdr (assoc 10 entData)) norm 0))
    )
  )
)

;;; VXV Returns the dot product of 2 vectors
(defun vxv (v1 v2)
  (apply '+ (mapcar '* v1 v2))
)

;; TRP Transpose a matrix -Doug Wilson-
(defun trp (m)
  (apply 'mapcar (cons 'list m))
)

;; MXV Apply a transformation matrix to a vector -Vladimir Nesterovsky-
(defun mxv (m v)
  (mapcar '(lambda (r) (vxv r v)) m)
)

;; MXM Multiply two matrices -Vladimir Nesterovsky-
(defun mxm (m q)
  (mapcar '(lambda (r) (mxv (trp q) r)) m)
)

; ==================================================================================================================================


;; Get Dynamic Block Property Value  -  Lee Mac
;; Returns the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)

(defun LM:getdynpropvalue ( blk prp )
    (setq prp (strcase prp))
    (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'value)))
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)


; ==================================================================================================================================


(defun C:ConnectStackedBlocks (/ isDynamicBlock build_data_list get_match_block_above drawline ; local functions
			         X_FAZZ Y_FAZZ dynamicBlocks^ adoc blocks bname ss i item0 item1	 ; local variables
			         ename0 ename1 lst AcDbBlkRef0 AcDbBlkRef1 dx0 dy0 dx1 dy1 p0 p1 p2 p3)  ; local variables

 (defun isDynamicBlock (ent / bname)
  (setq bname (cdr (assoc '2 (entget ent))))
  (cond
   ((member bname dynamicBlocks^)
    :vlax-true
   ); case
   ((eq (vla-get-isDynamicBlock (vla-item blocks bname)) :vlax-false)
    :vlax-false
   ); case
   ( t
    (setq dynamicBlocks^ (cons bname dynamicBlocks^))
    :vlax-true
   ); case
  ); cond
 ); isDynamicBlock

  
 (defun build_data_list (ss / lst ename pt item)
  (foreach ename (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
   (setq pt (cdr (assoc '10 (entget ename))))
   (if (eq (isDynamicBlock ename) :vlax-true)
    (cond
     ((not (vl-some '(lambda (item) (equal (car item) (cadr pt) X_FAZZ)) lst))
      (setq lst (cons (cons (cadr pt) (list ename)) lst))
     ); case
     ( t
      (setq lst (vl-remove (setq item (assoc (cadr pt) lst)) lst))
      (setq lst (cons (cons (car item) (cons ename (cdr item))) lst))
     ); case
    ); cond
   ); if
  ); foreach

  lst
 ); build_data_list

  
 (defun get_match_block_above (ename0 item1 / pt0)
  (setq pt0 (cdr (assoc '10 (entget ename0))))
  (vl-some
   '(lambda (ename1 / pt1)
     (setq pt1 (cdr (assoc '10 (entget ename1))))
     (if (equal (car pt0) (car pt1) Y_FAZZ)
      ename1 ; return
     )
    ); lambda
   (cdr item1)
  ); vl-some
 ); get_match_block_above


 (defun drawline (t0 t1)
  (entmake
    (list
     '(0 . "LINE")
      (cons 10 t0)
      (cons 11 t1)
    )
  )
 ); drawline
  
 ; here start C:ConnectStackedBlocks
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startUndoMark adoc)

 (setq X_FAZZ 1e-2 Y_FAZZ 1e-2) ; const

 (setq blocks (vla-get-blocks adoc))

 (if (setq ss (ssget (list '(0 . "insert"))))
  (progn
   (setq lst (vl-sort (build_data_list ss) (function (lambda (e0 e1) (< (car e0) (car e1))))))

   (setq i 0 item0 (nth i lst))
   (repeat (vl-list-length lst) ; loop main list
    (setq i (1+ i) item1 (nth i lst))

    (foreach ename0 (cdr item0) ; loop through bottom objects
     (if (setq ename1 (get_match_block_above ename0 item1)) ; get match block from above
      (progn
       (setq AcDbBlkRef0 (vlax-ename->vla-object ename0))
       (setq AcDbBlkRef1 (vlax-ename->vla-object ename1))
	  
       (if (and
	     (setq dx0 (LM:getdynpropvalue AcDbBlkRef0 "top x"))
	     (setq dy0 (LM:getdynpropvalue AcDbBlkRef0 "top y"))
	     (setq dx1 (LM:getdynpropvalue AcDbBlkRef1 "bottom x"))
	     (setq dy1 (LM:getdynpropvalue AcDbBlkRef1 "bottom y"))
	     (setq p0 (TransNested (list dx0 dy0 0.0) (list ename0) 2 1))
	     (setq p1 (list (+ (car p0) 0.1) (cadr p0)))
	     (setq p2 (TransNested (list dx1 dy1 0.0) (list ename1) 2 1))
	     (setq p3 (list (+ (car p2) 0.1) (cadr p2)))
           )
        (progn
         (drawline p0 p2) ; main wire
	 (drawline p1 p3) ; paralle wire
	); progn
       ); if

       (vlax-release-object AcDbBlkRef1)
       (vlax-release-object AcDbBlkRef0)
      ); progn
     ); if
    ); foreach

    (setq item0 item1)
   ); repeat
      
  ); progn
 ); if
  
 (vlax-release-object blocks)

 (vla-endUndoMark adoc)
 (vlax-release-object adoc)
	     
 (princ)
); C:ConnectStackedBlocks

 

 

Message 8 of 17

Moshe-A
Mentor
Mentor

@EnM4st3r  hi,

 

Made some fine tuning, replace the following code.

 

 

(defun C:ConnectStackedBlocks (/ isDynamicBlock build_data_list get_match_block_above drawline summarize  	; local functions
			       
                                 X_FAZZ Y_FAZZ notDynBlk notMatched notProp adoc blocks ss lst i item0 		; local variables
			         item1 ename0 ename1 AcDbBlkRef0 AcDbBlkRef1 dx0 dy0 dx1 dy1 p0 p1 p2 p3)	; local variables
			         
 (defun isDynamicBlock (ent / bname)
  (setq bname (cdr (assoc '2 (entget ent))))
  (cond
   ((member bname dynamicBlocks^)
    :vlax-true
   ); case
   ((eq (vla-get-isDynamicBlock (vla-item blocks bname)) :vlax-false)
    :vlax-false
   ); case
   ( t
    (setq dynamicBlocks^ (cons bname dynamicBlocks^))
    :vlax-true
   ); case
  ); cond
 ); isDynamicBlock

  
 (defun build_data_list (s0 / l ent pt itm)
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex s0)))
   (setq pt (cdr (assoc '10 (entget ent))))
   (if (eq (isDynamicBlock ent) :vlax-true)
    (cond
     ((not (vl-some '(lambda (itm) (equal (car itm) (cadr pt) Y_FAZZ)) l))
      (setq l (cons (cons (cadr pt) (list ent)) l))
     ); case
     ( t
      (setq l (vl-remove (setq itm (assoc (cadr pt) l)) l))
      (setq l (cons (cons (car itm) (cons ent (cdr itm))) l))
     ); case
    ); cond
    ; else
    (setq notDynBlk (1+ notDynBlk))
   ); if
  ); foreach

  l ; return
 ); build_data_list

  
 (defun get_match_block_above (ent0 itm1 / pt0)
  (setq pt0 (cdr (assoc '10 (entget ent0))))
  (vl-some
   '(lambda (ent1 / pt1)
     (setq pt1 (cdr (assoc '10 (entget ent1))))
     (if (equal (car pt0) (car pt1) X_FAZZ)
      ent1 ; return
     )
    ); lambda
   (cdr itm1)
  ); vl-some
 ); get_match_block_above


 (defun drawline (t0 t1)
  (entmake
    (list
     '(0 . "LINE")
      (cons 10 t0)
      (cons 11 t1)
    )
  )
 ); drawline


 (defun summarize ()
  (if (> notDynBlk 0)
   (prompt (strcat "\n" (itoa notDynBlk) " not dynamic block(s) skipped."))
  )
  (if (> notMatched 0)
   (prompt (strcat "\n" (itoa notMatched) " block(s) skipped, has no match above."))
  )
  (if (> notProp 0)
   (prompt (strcat "\n" (itoa notProp) " block(s) skipped, invalid TOP/BOTTOM properties."))
  )  
 ); summarize
 
  
 ; here start C:ConnectStackedBlocks
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startUndoMark adoc)

 ; initialize global counters
 (foreach var (list 'notDynBlk 'notMatched 'notProp)
  (set var 0)
 )

 (setq X_FAZZ 1e-2 Y_FAZZ 1e-2) ; const
 (setq blocks (vla-get-blocks adoc))

 (if (setq ss (ssget (list '(0 . "insert"))))
  (progn
   (setq lst (vl-sort (build_data_list ss) (function (lambda (e0 e1) (< (car e0) (car e1))))))
  
   (setq i 0 item0 (nth i lst))
   (repeat (1- (vl-list-length lst)) ; loop main list
    (setq i (1+ i) item1 (nth i lst))

    (foreach ename0 (cdr item0) ; loop through bottom objects
     (if (setq ename1 (get_match_block_above ename0 item1)) ; get match block from above row
      (progn
       (setq AcDbBlkRef0 (vlax-ename->vla-object ename0))
       (setq AcDbBlkRef1 (vlax-ename->vla-object ename1))
  
       (if (and
	     (setq dx0 (LM:getdynpropvalue AcDbBlkRef0 "top x"))
	     (setq dy0 (LM:getdynpropvalue AcDbBlkRef0 "top y"))
	     (setq dx1 (LM:getdynpropvalue AcDbBlkRef1 "bottom x"))
	     (setq dy1 (LM:getdynpropvalue AcDbBlkRef1 "bottom y"))
	     (setq p0 (TransNested (list dx0 dy0 0.0) (list ename0) 2 1))
	     (setq p1 (list (+ (car p0) 0.1) (cadr p0)))
	     (setq p2 (TransNested (list dx1 dy1 0.0) (list ename1) 2 1))
	     (setq p3 (list (+ (car p2) 0.1) (cadr p2)))
           )
        (progn
         (drawline p0 p2) ; main wire
	 (drawline p1 p3) ; paralle wire
	); progn
	; else
	(setq notProp (1+ notProp))
       ); if

       ; dispose memory
       (vlax-release-object AcDbBlkRef1)
       (vlax-release-object AcDbBlkRef0)
      ); progn
      ; else
      (setq notMatched (1+ notMatched))      
     ); if
    ); foreach

    (setq item0 item1)
   ); repeat
      
  ); progn
 ); if

 (summarize)
 (vlax-release-object blocks) ; dispose memory

 (vla-endUndoMark adoc)
 (vlax-release-object adoc) ; dispose memory
	     
 (princ)
); C:ConnectStackedBlocks

 

Message 9 of 17

CodeDing
Advisor
Advisor
Accepted solution

@imegusta02 ,

 

Here's my try at it:

LED.gif

 

Lisp Code:

 

(defun c:LED ( / ssBlk sortedBlocks)
  (prompt "\nSelect LED Blocks to connect: ")
  (if (setq ssBlk (ssget '((0 . "INSERT") (2 . "LED_PATH_C_V2"))))
    (progn
      (ConnectBlocks
        (SortBlocks ssBlk)
      )
      (prompt "\nLED Complete.")
    );progn
  ;else
    (prompt "\nNo blocks selected.")
  );if
  (princ)
)

(defun FilterList (lst filter / return)
  (foreach i lst
    (if (filter i)
      (setq return (cons i return))
    );if
  );foreach
  (reverse return)
);defun

(defun SortBlocks (ssBlk / cnt e pt oTop oBot blocks x stack return)
  (repeat (setq cnt (sslength ssBlk))
    (setq e (ssname ssBlk (setq cnt (1- cnt)))
          pt (cdr (assoc 10 (entget e)))
          oTop (list (getpropertyvalue e "AcDbDynBlockPropertyTOP X")
                     (getpropertyvalue e "AcDbDynBlockPropertyTOP Y"))
          oBot (list (getpropertyvalue e "AcDbDynBlockPropertyBOTTOM X")
                     (getpropertyvalue e "AcDbDynBlockPropertyBOTTOM Y"))
          blocks (cons (list e pt oTop oBot) blocks)
    );setq
  );repeat
  (setq blocks (vl-sort blocks '(lambda (x y) (< (cadadr x) (cadadr y))))
        blocks (vl-sort blocks '(lambda (x y) (< (caadr x) (caadr y))))
  );setq
  (while blocks
    (setq x (caadar blocks)
          stack (FilterList blocks (lambda (b) (equal x (caadr b) 0.01)))
          return (cons stack return)
    );setq
    (repeat (length stack) (setq blocks (cdr blocks)))
  );while
  (reverse return)
);defun

(defun ConnectBlocks (sb / Line lastBlk lastOffset lastPt offset pt)
  (defun Line (p1 p2)
    (entmakex (list (cons 0 "LINE") (cons 10 p1) (cons 11 p2)))
  )
  (foreach stack sb
    (setq lastBlk (car stack))
    (foreach blk (cdr stack)
      (setq lastOffset (caddr lastBlk)
            lastPt (mapcar '+ (cadr lastBlk) lastOffset)
            offset (cadddr blk)
            pt (mapcar '+ (cadr blk) offset)
      );setq
      (Line lastPt pt)
      (Line (polar lastPt 0 0.1) (polar pt 0 0.1))
      (setq lastBlk blk lastOffset offset lastPt pt)
    );foreach
  );foreach
);defun

 

Message 10 of 17

imegusta02
Participant
Participant

Oh wow thanks that's exactly what I was trying to achieve. One quick question tho, what would I have to do/change if I want to connect more points together something like the image I provided, I assume I'd have to make more point parameters in the block itself but how would this be added in the code you provided? Thanks in advance

0 Likes
Message 11 of 17

imegusta02
Participant
Participant
thanks but this is to connect the insertion points to one another which isn't really what I'm looking for.
0 Likes
Message 12 of 17

CodeDing
Advisor
Advisor

@imegusta02 ,

 

If you zoom in to my created lines, you see that it already creates 2 of them like in your example drawing. That is accomplished with these two lines of code: 

(Line lastPt pt)
(Line (polar lastPt 0 0.1) (polar pt 0 0.1))

 

You can add more lines by using more Line/polar functions, if you understand how those work. 

 

Best,

~DD

0 Likes
Message 13 of 17

imegusta02
Participant
Participant
I'm not that familiar with them to be honest but if I understand it correctly it draws a line from lastPT to pt and then offsets the next line the required 0.1 for both points, so if I want to do it for the other connections I just have to measure the distance and use those for the offset values right?
Message 14 of 17

CodeDing
Advisor
Advisor

Correct,

 

The (polar ...) function creates a point by taking:

- a point [pt], as a starting location [in our case, lastPt or pt]

- an angle [ang], in radians, as a direction to travel [i used 0, because that is directly to the right (pi would be to the left)]

- a distance [dist], as the distance to travel [i used 0.1 in my code]

 

so as long as you use that info, you can create a new line anywhere you wish.

 

Best,

~DD

Message 15 of 17

Moshe-A
Mentor
Mentor
Accepted solution

@imegusta02  hi,

 

Modified mine to meet your last requests.

 

Attached the full lisp + your dwg with 2 wires as sample.

what i did is changed the properties point name to BOOTOM1\TOP1 and add another called it BOTTOM4\TOP4

 

Now look in middle code (lines 28-29)

i call (dwire n) function twice with an argument 1 & 4.

you can add more dynamic points the same way than add the calls and job done 😀

 

work?

 

 

 

; here start C:ConnectStackedBlocks
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startUndoMark adoc)

  ; initialize global counters
 (foreach var (list 'notDynBlk 'notMatched 'notProp)
  (set var 0)
 )

 (setq X_FAZZ 1e-2 Y_FAZZ 1e-2) ; const
 (setq blocks (vla-get-blocks adoc))

 (if (setq ss (ssget (list '(0 . "insert"))))
  (progn
   (setq lst (vl-sort (build_data_list ss) (function (lambda (e0 e1) (< (car e0) (car e1))))))
    
   (setq i 0 item0 (nth i lst))
   (repeat (1- (vl-list-length lst)) ; loop main list
    (setq i (1+ i) item1 (nth i lst))
    (foreach ename0 (cdr item0) ; loop through bottom objects
     (if (setq ename1 (get_match_block_above ename0 item1)) ; get match block from above row
      (progn
       (setq AcDbBlkRef0 (vlax-ename->vla-object ename0))
       (setq AcDbBlkRef1 (vlax-ename->vla-object ename1))

       (if (not
	     (and
	      (dwire 1) ; draw first lines
	      (dwire 4) ; draw forth lines
	     )
           )
	(setq notProp (1+ notProp))
       )
  
       ; dispose memory
       (vlax-release-object AcDbBlkRef1)
       (vlax-release-object AcDbBlkRef0)
      ); progn
      ; else
      (setq notMatched (1+ notMatched))      
     ); if
    ); foreach

    (setq item0 item1)
   ); repeat
      
  ); progn
 ); if

 (summarize)
 (vlax-release-object blocks) ; dispose memory

 (vla-endUndoMark adoc)
 (vlax-release-object adoc) ; dispose memory
	     
 (princ)
)

 

 

 

 

Message 16 of 17

imegusta02
Participant
Participant
Awesome, thanks a lot 🙂
0 Likes
Message 17 of 17

imegusta02
Participant
Participant
Thank you very much, now I can continue working on the rest of the script for the entire project 🙂
0 Likes