Author Topic: Why can't I undo with a single "undo"?  (Read 848 times)

0 Members and 1 Guest are viewing this topic.

Clujna

  • Mosquito
  • Posts: 12
  • Juanjo, draftsman
Why can't I undo with a single "undo"?
« on: November 06, 2021, 09:55:21 AM »
Hi all.
I have tried it in the two ways I know, but in both cases when I want to undo the command I have to press "undo" 3 times so that "OSMODE" returns to its original state.

Command version:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:ALIGN2D (/ osmorig sel o1 m1 o2 m2)
  2.   (command "_UNDO" "_BEGIN")
  3.   (defun *error* (msg)
  4.     (princ "error: ")
  5.     (princ msg)
  6.     (setvar 'OSMODE osmorig))
  7.   (setq osmorig (getvar 'OSMODE))
  8.   (setq sel (ssget))
  9.   (setq o1 (getpoint "\nSpecify first source point: "))
  10.   (setq m1 (getpoint o1 "\nSpecify first destination point: "))
  11.   (setq o2 (getpoint "\nSpecify second source point: "))
  12.   (setq m2 (getpoint o2 "\nSpecify second destination point: "))
  13.   (setvar 'OSMODE 0)
  14.   (command "_ALIGN" sel ""
  15.     (strcat (rtos (car o1) 2 16) "," (rtos (cadr o1) 2 16))
  16.     (strcat (rtos (car m1) 2 16) "," (rtos (cadr m1) 2 16))
  17.     (strcat (rtos (car o2) 2 16) "," (rtos (cadr o2) 2 16))
  18.     (strcat (rtos (car m2) 2 16) "," (rtos (cadr m2) 2 16))
  19.     "" "")
  20.   (setvar 'OSMODE osmorig)
  21.   (command "_UNDO" "_END")
  22.   (princ)
  23. )

And VLA version:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:ALIGN2D (/ doc osmorig sel o1 m1 o2 m2)
  2.   (defun *error* (msg)
  3.     (princ "error: ")
  4.     (princ msg)
  5.     (setvar 'OSMODE osmorig))
  6.   (setq osmorig (getvar 'OSMODE))
  7.   (setq sel (ssget))
  8.   (setq o1 (getpoint "\nSpecify first source point: "))
  9.   (setq m1 (getpoint o1 "\nSpecify first destination point: "))
  10.   (setq o2 (getpoint "\nSpecify second source point: "))
  11.   (setq m2 (getpoint o2 "\nSpecify second destination point: "))
  12.   (setvar 'OSMODE 0)
  13.   (command "_ALIGN" sel ""
  14.     (strcat (rtos (car o1) 2 16) "," (rtos (cadr o1) 2 16))
  15.     (strcat (rtos (car m1) 2 16) "," (rtos (cadr m1) 2 16))
  16.     (strcat (rtos (car o2) 2 16) "," (rtos (cadr o2) 2 16))
  17.     (strcat (rtos (car m2) 2 16) "," (rtos (cadr m2) 2 16))
  18.     "" "")
  19.   (setvar 'OSMODE osmorig)
  20.   (princ)
  21. )
  22.  
What am I doing wrong? Is there a way to undo the command with a single "undo"?



EDIT (John): Added code tags.
« Last Edit: November 06, 2021, 12:54:06 PM by John Kaul (Se7en) »
Juan José Bernal, civil works draftsman

ribarm

  • Gator
  • Posts: 3274
  • Marko Ribar, architect
Re: Why can't I undo with a single "undo"?
« Reply #1 on: November 06, 2021, 11:50:50 AM »
It is because ALIGN command is little specific - it uses (align) ALISP function which already has built-in undo mark statements... ALIGN can't be performed directly by using transformation - modification of source objects once - it uses instead multiple commands and therefore they had to be wrapped in UNDO group... So after you call ALIGN command, one UNDO takes you back right before you call ALIGN - built-in undo mark activates, so at that point your OSMODE = 0, just like you coded - so you need UNDO again to take you back to your undo mark were OSMODE = osmorig... As a workaround I suggest that you use either 2nd or 3rd mod. of your routine since first just do what you did and prompt user to type "UNDO" "B" for back which is IMHO somewhat cumbersome...

Code: [Select]
(defun c:ALIGN2D (/ *error* osmorig sel o1 m1 o2 m2)
  (defun *error* (msg)
    (princ "error: ")
    (princ msg)
    (setvar 'OSMODE osmorig))
  (if (= 8 (logand 8 (getvar 'UNDOCTL)))
    (command "_.UNDO" "_END")
  )
  (command "_.UNDO" "_GROUP")
  (setq osmorig (getvar 'OSMODE))
  (setq sel (ssget "_:L"))
  (setq o1 (getpoint "\nSpecify first source point: "))
  (setq m1 (getpoint o1 "\nSpecify first destination point: "))
  (setq o2 (getpoint "\nSpecify second source point: "))
  (setq m2 (getpoint o2 "\nSpecify second destination point: "))
  (setvar 'OSMODE 0)
  (command "_.ALIGN" sel ""
    (strcat (rtos (car o1) 2 16) "," (rtos (cadr o1) 2 16))
    (strcat (rtos (car m1) 2 16) "," (rtos (cadr m1) 2 16))
    (strcat (rtos (car o2) 2 16) "," (rtos (cadr o2) 2 16))
    (strcat (rtos (car m2) 2 16) "," (rtos (cadr m2) 2 16))
    "" "")
  (setvar 'OSMODE osmorig)
  (command "_.UNDO" "_END")
  (prompt "\nType \"UNDO\" \"B\" (back) for back...")
  (princ)
)

(defun c:ALIGN2D (/ *error* osmorig sel o1 m1 o2 m2)
  (defun *error* (msg)
    (princ "error: ")
    (princ msg)
    (setvar 'OSMODE osmorig))
  (if (= 8 (logand 8 (getvar 'UNDOCTL)))
    (command "_.UNDO" "_END")
  )
  (command "_.UNDO" "_GROUP")
  ;(setq osmorig (getvar 'OSMODE))
  (setq sel (ssget "_:L"))
  (setq o1 (getpoint "\nSpecify first source point: "))
  (setq m1 (getpoint o1 "\nSpecify first destination point: "))
  (setq o2 (getpoint "\nSpecify second source point: "))
  (setq m2 (getpoint o2 "\nSpecify second destination point: "))
  ;(setvar 'OSMODE 0)
  (align sel o1 m1 o2 m2 "" "")
  ;|
  (command "_.ALIGN" sel ""
    (strcat (rtos (car o1) 2 16) "," (rtos (cadr o1) 2 16))
    (strcat (rtos (car m1) 2 16) "," (rtos (cadr m1) 2 16))
    (strcat (rtos (car o2) 2 16) "," (rtos (cadr o2) 2 16))
    (strcat (rtos (car m2) 2 16) "," (rtos (cadr m2) 2 16))
    "" "")
  |;
  ;(setvar 'OSMODE osmorig)
  (command "_.UNDO" "_END")
  (princ)
)

(defun c:ALIGN2D (/ *error* osmorig sel o1 m1 o2 m2)
  (defun *error* (msg)
    (princ "error: ")
    (princ msg)
    (setvar 'OSMODE osmorig))
  (if (= 8 (logand 8 (getvar 'UNDOCTL)))
    (command "_.UNDO" "_END")
  )
  (command "_.UNDO" "_GROUP")
  ;(setq osmorig (getvar 'OSMODE))
  (setq sel (ssget "_:L"))
  (setq o1 (getpoint "\nSpecify first source point: "))
  (setq m1 (getpoint o1 "\nSpecify first destination point: "))
  (setq o2 (getpoint "\nSpecify second source point: "))
  (setq m2 (getpoint o2 "\nSpecify second destination point: "))
  ;(setvar 'OSMODE 0)
  (command "_.ALIGN" sel ""
    "_non" (strcat (rtos (car o1) 2 16) "," (rtos (cadr o1) 2 16))
    "_non" (strcat (rtos (car m1) 2 16) "," (rtos (cadr m1) 2 16))
    "_non" (strcat (rtos (car o2) 2 16) "," (rtos (cadr o2) 2 16))
    "_non" (strcat (rtos (car m2) 2 16) "," (rtos (cadr m2) 2 16))
    "" "")
  ;(setvar 'OSMODE osmorig)
  (command "_.UNDO" "_END")
  (princ)
)

HTH.

BTW. I modified your original code to include localizing error handler, to check if previous UNDO mark was ENDED and added "_:L" mode for selection set acquiring since you can't apply ALIGN or any other mod. with selected entities that belong to locked layer(s)...

[EDIT]
P.S. This problem is not relevant for users of BricsCAD, since (I suppose) (align) function was better implemented. After single UNDO, ESNAPs work... ESNAP(BricsCAD)=OSNAP(AutoCAD)
[/EDIT]
« Last Edit: November 06, 2021, 12:29:08 PM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Clujna

  • Mosquito
  • Posts: 12
  • Juanjo, draftsman
Re: Why can't I undo with a single "undo"?
« Reply #2 on: November 07, 2021, 04:08:38 AM »
Thanks Marko. The third modification works perfectly. In fact, in it the code can be simplified even more (I think), since the error subroutine becomes unnecessary by not modifying "OSMODE" at any time:
(defun c:ALIGN2D (/ sel o1 m1 o2 m2)
  (if (= 8 (logand 8 (getvar 'UNDOCTL)))
    (command "_.UNDO" "_END")
  )
  (command "_.UNDO" "_GROUP")
  (setq sel (ssget "_:L"))
  (setq o1 (getpoint "\nSpecify first source point: "))
  (setq m1 (getpoint o1 "\nSpecify first destination point: "))
  (setq o2 (getpoint "\nSpecify second source point: "))
  (setq m2 (getpoint o2 "\nSpecify second destination point: "))
  (command "_.ALIGN" sel ""
    "_non" (strcat (rtos (car o1) 2 16) "," (rtos (cadr o1) 2 16))
    "_non" (strcat (rtos (car m1) 2 16) "," (rtos (cadr m1) 2 16))
    "_non" (strcat (rtos (car o2) 2 16) "," (rtos (cadr o2) 2 16))
    "_non" (strcat (rtos (car m2) 2 16) "," (rtos (cadr m2) 2 16))
    "" "")
  (command "_.UNDO" "_END")
  (princ)
)
Juan José Bernal, civil works draftsman