HI All,
I have a suite of routines that rely on entities being on locked layers. In essence, everytime you need to work with one of those entities, the programs unlock all the possible layers and the user is able to manipulate the objects. Once finished, the layers get locked up again. These routines never had problems, untill the modeless layer dialogue was introduced (back in 2008??). Now it takes about 10+ seconds for the program to go through the lock or unlock process (the layerdlgmode variable didn't make any difference either):
(setq pind 0)
(repeat (length pdpurlinlist)
(command "_.-layer" "unlock" (nth pind pdpurlinlist) "")
(setq pind (+ 1 pind))
)
Curious thing is that if the layers are already unlocked, the code gets executed almost instantly. If the layer were locked and the program has to unlock them, then it takes about 10 seconds to unlock 4 layers.
Has anyone else found a similar problem and is there an alternative way to lock/unlock layers in lisp which might process a bit quicker?
Thanks in advance.
John
Solved! Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Solved by Kent1Cooper. Go to Solution.
@iwafb wrote:.... the programs unlock all the possible layers and the user is able to manipulate the objects. Once finished, the layers get locked up again. ....it takes about 10+ seconds for the program to go through the lock or unlock process....
....is there an alternative way to lock/unlock layers in lisp which might process a bit quicker?
....
Try something like this:
(setq layUlist ; list of locked layers among those in pdpurlinlist (vl-remove-if-not '(lambda (lay) (= (logand (cdr (assoc 70 (tblsearch "layer" lay))) 4) 4) ); end lambda pdpurlinlist ); end vl-remove-if-not ); end setq (foreach lay layUlist ; unlock those layers (setq laydata (entget (tblobjname "layer" lay)) laydata (subst (cons 70 (- (cdr (assoc 70 laydata)) 4)) (assoc 70 laydata) laydata ); end subst ); end setq (entmod laydata) ); end foreach ;;;;..........do your thing to the objects.......... (foreach lay layUlist ; re-lock those layers (setq laydata (entget (tblobjname "layer" lay)) laydata (subst (cons 70 (+ (cdr (assoc 70 laydata)) 4)) (assoc 70 laydata) laydata ); end subst ); end setq (entmod laydata) ); end foreach
@iwafb wrote:....
(setq pind 0)
(repeat (length pdpurlinlist)
(command "_.-layer" "unlock" (nth pind pdpurlinlist) "")
(setq pind (+ 1 pind))
)....
By the way, though it may not save any time if the (command) approach is the cause of the delay, there is a simpler way to do this, when it's a list you're working on [not, for example, a selection set]:
(foreach lay pdpurlinlist
(command "_.layer" "unlock" lay "")
)
But that still invokes the (command) function for every Layer involved, which is likely the biggest time-consumer. It probably would save time, even if using (command), to use it only once:
(setq layUlist ""); initial empty string
(foreach lay pdpurlinlist (setq layUlist (strcat layUlist lay ","))); comma-delimited string of Layer names
(command "_.layer" "_unlock" layUlist "")
Your original and these other approaches would unlock all Layers in the list. But your original message suggests that you would need to know which are locked when you start, so you can lock them again later, without also locking Layers that were not locked when you started. That made me think maybe your pdpurlinlist was already a list of only locked Layers, but that doesn't jive with your statement that "if the layers are already unlocked, the code gets executed almost instantly." I don't know how you've been doing the re-locking [maybe you've been locking Layers that were unlocked before], but my earlier suggestion makes such a pared-down list, so you can use it again later to re-lock only the Layers that were locked.
Might the faded color feature of locked layers have something to do with the delay? Seems that as each layer is locked/unlocked the screen would be updated, which could account for the extra time involved.
Thanks to all for your suggestions.
I was not aware of Kent's approach in staying away from using the command method. I will definitely give that a try.
Just to clarify, pdpurlinlist is a list of all locked layers. I only noticed the difference in time because while I was running testing I couldn't figure out why sometimes the program stepped through those lines in no time, and sometimes it hang. Under normal circumstances, the layers would always be locked before execution. Sorry about the confusion.
Also, I turned fading off for locked layers as I didn't like it. Still, this program never seemed to hang prior to about Acad2007. So there might be some merit in dgorsman's thinking??
Thanks again
John
BTW - I've actually gained two "nuggets of wisdom" from this post, as I've never really used the foreach approach given that I didn't really understand the advantages. Will consider a lot more in the future...
Done and it works absolutely perfect!!! Routine now has no lag at all.
Can you maybe shed some light on this though?
The only difference I can see in the two function is the + or - in the cons line. I kind of assumed this would be the switch to lock/unlock the layer, which seems to be the case witht he - (unlock). However, the + (lock) seems to work more as a toggle? That is if the layer is locked it will unlock it and viceversa. Is that the way it works?
Thanks
John
@iwafb wrote:....
The only difference I can see in the two function is the + or - in the cons line. I kind of assumed this would be the switch to lock/unlock the layer, which seems to be the case witht he - (unlock). However, the + (lock) seems to work more as a toggle? That is if the layer is locked it will unlock it and viceversa. Is that the way it works?
....
The information about a Layer that you get from either
(tblsearch "layer" "YourLayerName")
or
(entget (tblobjname "layer" "YourLayerName"))
contains an entry that looks like this:
(70 . 0)
except that the second number isn't always a 0. It's a binary-bit code that holds information about a couple of things. If it's 0, the Layer is thawed and unlocked. If the Layer is frozen, that second number includes the 1 binary bit. If it's locked, it includes the 4 bit. If it's frozen but not locked, it will be 1; if it's locked but not frozen, it will be 4; and if it's both locked and frozen, it will be 5 [the sum of the other two]. I'm not sure whether other binary-bit numbers [2, 8, 16, etc.] are used, but knowing that the 4 bit is about locking is all that's necessary here.
If a Layer is locked, the number paired with the 70 will be 4 or 5 [or if 2 is used for something I'm not aware of, possibly 6 or 7, etc., but always something whose makeup as a sum of power-of-2 integers includes a 4] -- subtracting 4 from whatever it is will unlock the Layer. If it's unlocked, that number will be 0 or 1 [or 2 or 3 or 8 or 9, etc., but always something whose powers-of-2 makeup does not include a 4] -- adding 4 to whatever it is will lock the Layer.
The (cdr) functions find the current value paired with 70, the (cons) functions pair the result of subtracting or adding 4 from or to that with a 70, the (subst) functions replace the old 70-code pair with the new one, and the (entmod) functions impose that change on the database.
Kent, I like how you use tblsearch to move through the layer list. Nice code. Just for giggles, here is something I use in my routines to unlock all layers. I set a variable to create a list of all locked layers (if any) and use that list at the end of the routine to lock them again.
; SETQ "DOC" TO THE ACTIVE DOCUMENT.
(setq doc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
; UNLOCK ALL LAYERS
(vlax-for item (vla-get-layers doc)
(if (= (vlax-get-property item "Lock") :vlax-true)
(progn
(setq Locked_Layers (cons item Locked_Layers)) ; SET VARIABLE "LOCKED_LAYERS" TO ALL LOCKED LAYERS.
(vlax-put-property item "Lock" :vlax-false) ; UNLOCK EACH LAYER IF IT IS LOCKED.
); end progn
); end if
); end vlax
(*** Place your code here ***)
; IF ANY LAYERS WERE LOCKED AT THE BEGINNING, LOCK THEM AGAIN.
(if Locked_Layers
(mapcar '(lambda(x)(vlax-put-property x "Lock" :vlax-true)) Locked_Layers)
); end if
Jim
@markruys2 wrote:you can use a simpler approach
(command "._-layer")
(foreach lay laylist (command "_unlock" lay))
(command "")
[Look back at Messages 3 for a similar approach, and 7 for confirmation that the (command) function was apparently the cause of the slowness. I imagine nesting (command) functions inside each other would only exacerbate that.]