3dwannab Posted September 5 Posted September 5 (edited) Hi all, I have the bones of a program to stretch along either the X or Y direction only. I just need help toggling between the two modes by either pressing X or Y on the keyboard so I can seamlessly toggle between the two. Or, ideally, be able to hold down a modifier key to toggle. Currently with the code once I'm in a mode I can't get out of it. Here's the code: ;; Stretch all in X or Y direction ;; ;; TO DO: Need to get a correct way to toggle between X and Y mode ;; ;; NOTE: Ideally, I would like the shift key to toggle modes. ;; (defun c:SXY (/ *error* mod var_cmdecho var_osmode var_orthomode ss1) (defun *error* (errmsg) (and acDoc (vla-EndUndoMark acDoc)) (and errmsg (not (wcmatch (strcase errmsg) "*CANCEL*,*EXIT*")) (princ (strcat "\n<< Error: " errmsg " >>\n")) ) (setvar 'cmdecho var_cmdecho) (setvar 'osmode var_osmode) ) ;; Start the undo mark here (setq acDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (or (vla-EndUndoMark acDoc) (vla-StartUndoMark acDoc)) ;; Get any system variables here (setq var_cmdecho (getvar "cmdecho")) (setq var_osmode (getvar "osmode")) (setq var_orthomode (getvar "orthomode")) (setvar 'cmdecho 0) (setvar 'osmode 223) (setvar 'orthomode 1) (while (and (setq g (grread t 15 0))) (if (= "y" (chr (cadr g))) (setq mod ".xz")) (if (= "x" (chr (cadr g))) (setq mod ".yz")) (progn (while (= 0 (logand 0 (getvar 'cmdactive))) (progn (if (= "x" (chr (cadr g))) (progn (setq mod ".yz") (princ "\nStretch along X axis..."))) (if (= "y" (chr (cadr g))) (progn (setq mod ".xz") (princ "\nStretch along Y axis..."))) (princ "\n") (princ mod) (princ "\n") (command "_.stretch" (setq ss1 (ssget '((0 . "~XLINE")))) "" PAUSE mod "@") (vl-cmdf "\\") ) ) ) ) ; while (vla-EndUndoMark acDoc) (*error* nil) (princ) ) Edited September 5 by 3dwannab Quote
pkenewell Posted September 5 Posted September 5 Here is my solution: 1) you needed to account for if capslock is on so always force the "x" or "y" to lowercase. 2) you needed a way to exit the loop. i added a condition to test if ENTER or SPACEBAR were pressed to set variable "ret" to T, then test a value in "ret" at the top of the loop. 3) See the changes I made to your command loop to prevent the command from running on unnecessarily, you can play with this if you want by changing the IF to a WHILE for the selection set. ;; Stretch all in X or Y direction ;; ;; TO DO: Need to get a correct way to toggle between X and Y mode ;; (defun c:SXY (/ *error* var_cmdecho var_osmode var_orthomode ss1 ret) (defun *error* (errmsg) (and acDoc (vla-EndUndoMark acDoc)) (and errmsg (not (wcmatch (strcase errmsg) "*CANCEL*,*EXIT*")) (princ (strcat "\n<< Error: " errmsg " >>\n")) ) (setvar 'cmdecho var_cmdecho) (setvar 'osmode var_osmode) ) ;; Start the undo mark here (setq acDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (or (vla-EndUndoMark acDoc) (vla-StartUndoMark acDoc)) ;; Get any system variables here (setq var_cmdecho (getvar "cmdecho")) (setq var_osmode (getvar "osmode")) (setq var_orthomode (getvar "orthomode")) (setvar 'cmdecho 1) (setvar 'osmode 223) (setvar 'orthomode 1) (while (and (setq g (grread t 15 0))(not ret)) (princ "\rPress \"X\" or \"Y\" to start stretching, or [ENTER] to exit: ") (cond ((= 2 (car g)) (cond ((= "x" (strcase (chr (cadr g)) T)) ;; Stretch along X axis (progn (princ "\nStretch along X axis...") (if (setq ss1 (ssget '((0 . "~XLINE")))) (progn ; (command "_.stretch" (setq ss1 (ssget '((0 . "~HATCH") (0 . "~XLINE")))) "" PAUSE ".yz" "@") (command "_.stretch" ss1 "" PAUSE ".yz" "@") (while (= (logand (getvar "cmdactive") 1) 1) (command pause) ) ) ) ) ) ((= "y" (strcase (chr (cadr g)) T)) ;; Stretch along y axis (progn (princ "\nStretch along Y axis...") (if (setq ss1 (ssget '((0 . "~XLINE")))) (progn ; (command "_.stretch" (setq ss1 (ssget '((0 . "~HATCH") (0 . "~XLINE")))) "" PAUSE ".xz" "@") (command "_.stretch" ss1 "" PAUSE ".xz" "@") (while (= (logand (getvar "cmdactive") 1) 1) (command pause) ) ) ) ) ) ((vl-position (cadr g) '(13 32)) ;; Enter or Spacebar (setq ret T) ) ) ) ) ) (vla-EndUndoMark acDoc) (*error* nil) (princ) ) Quote
Steven P Posted September 5 Posted September 5 I was just looking at this, I might be getting this wrong. pkenewell, it asks for x, y or enter, then select object and then stretches, then returns to x, y, or enter. X, Y or enter done by grread - but that is only for selectin the direction and nothing else, and you can't modify the direction untill the next loop. So why not just have a getstring, with if string = X, Y or space? Quote
pkenewell Posted September 5 Posted September 5 23 minutes ago, Steven P said: I was just looking at this, I might be getting this wrong. pkenewell, it asks for x, y or enter, then select object and then stretches, then returns to x, y, or enter. X, Y or enter done by grread - but that is only for selectin the direction and nothing else, and you can't modify the direction untill the next loop. So why not just have a getstring, with if string = X, Y or space? @Steven P That's true of course. The grread however does eliminate the extra "enter" after the X or Y selection, but it's more of just trying to keep with the original intent of the OP. That being said - I think the OP would rather have the X or Y switchable on the fly mid-command, I don't think that will work within the command statement. I'll have to spend more time on it, if I get more time. You are welcome to propose your own solution. 1 Quote
3dwannab Posted September 5 Author Posted September 5 34 minutes ago, pkenewell said: I think the OP would rather have the X or Y switchable on the fly mid-command, I don't think that will work within the command statement I do and I'm at a loss as to how this could be accomplished. Thanks for your time spent on this. 1 Quote
BIGAL Posted September 5 Posted September 5 Google detect arrow key, you can get which key has been pressed. So 4 directions. Hmmm thinking maybe something by Lee-Mac. Quote
3dwannab Posted September 6 Author Posted September 6 18 minutes ago, BIGAL said: Google detect arrow key I know how to get the key presses alright, it's just having the ability to toggle inside the stretch command in the X and Y direction is the problem. I don't think what I want is possible. Quote
Jonathan Handojo Posted September 6 Posted September 6 8 minutes ago, 3dwannab said: I know how to get the key presses alright, it's just having the ability to toggle inside the stretch command in the X and Y direction is the problem. I don't think what I want is possible. I don't think (command) works in line with (grread). I might be wrong, but in my opinion, once the "command" is executed, any dynamic inputs will still be processed inside "command" until the user takes the required action to complete/exit the command, and only then the rest of grread is processed. I can't think of any possible approach to this other than making an entirely new STRETCH function that voids the calling of the COMMAND function for objects that would hopefully suit your needs. Quote
Steven P Posted September 6 Posted September 6 7 hours ago, BIGAL said: Google detect arrow key, you can get which key has been pressed. So 4 directions. Hmmm thinking maybe something by Lee-Mac. Does grread do arrow keys? (princ (grread)) doesn't show anything Quote
pkenewell Posted September 6 Posted September 6 (edited) 6 hours ago, Steven P said: Does grread do arrow keys? (princ (grread)) doesn't show anything That's correct; the Arrow keys don't seem to respond to calls within a grread loop. I have a test program that returns the code and data values, and the arrow keys do not return anything. Edited September 6 by pkenewell 1 Quote
3dwannab Posted September 6 Author Posted September 6 (edited) The poster said that their up/down keys work but on my machine, they don't. Quote This is a little strange, the Up/Down arrow keys work, but the Right/Left do not ?. Also try the NumLock Off, and the Arrow Keys there work real well. Taken from https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/using-arrow-keys/m-p/940812#M139501 Edited September 6 by 3dwannab Quote
mhupp Posted September 6 Posted September 6 21 hours ago, 3dwannab said: I know how to get the key presses alright, it's just having the ability to toggle inside the stretch command in the X and Y direction is the problem. I don't think what I want is possible. https://www.foreui.com/articles/Key_Code_Table.htm Quote
pkenewell Posted September 9 Posted September 9 @mhupp The arrow key codes (char 37-40) - at least on my keyboard - only work in the context of the number pad when number lock of OFF. The separate arrow keys return nothing to grread; no code 2, no char. data. 2 Quote
BIGAL Posted September 9 Posted September 9 Just a comment re stretch, if you do F8 ortho on, select object to stretch, pick point then drag mouse it will go in desired direction X or Y. Then type distance. No code. 2 Quote
Steven P Posted September 10 Posted September 10 Using some LISP to do the same thing, forces Y direction only in this case (change (0 1 0) where the 1 applies to (x y z) axis) but no changes to ortho state (removes need for error checking to return ortho state to what it was before running the LISP on 'escape'), looses the 'elastic band' though (command "_.stretch" (ssget) "" (mapcar '* '(0 1 0) (setq pt2 (getpoint))) (mapcar '* '(0 1 0) (setq pt3 (getpoint)))) I had a quiet start to the week yesterday, so had a look - using grread to switch X or Y axis is not really satisfactory without a lot of messing about - a quiet day yesterday so I did just that but not to a state to make it worth posting yet. Today 'they' want me to work, weirdos. 1 1 Quote
Steven P Posted September 10 Posted September 10 (edited) This is taking the above a little further, but is not as finished as I might want. The user can alter the direction before or after selecting the entities rather than selecting the direction and then the entities. I reckon if you are using grread in something similar you are wanting quite a complex solution, most users are happy with 'select an option and enter' to continue. A bit of work to do another time so show the rubber bands for the stretches and to add in object snaps, but I am just adding this in here as an example - I might get more chance to look at this another day. (defun c:GRStretch ( / mod MyDist MyEnt MySS pt1 pt2 pt3 pt4 endloop acount) (setq endloop "No") (setq mod "X") (princ (strcat "Press \"X\" or \"Y\" [" mod "], select entities to stretch, or [ENTER] to exit: ")) (while (and (setq g (grread t 14 2)) (= endloop "No") ) (cond ((= (car g) 2) ;;Set mode - text entry (if (or (= 88 (cadr g))(= 120 (cadr g))) (setq mod "X")) ; x, X (if (or (= 89 (cadr g))(= 121 (cadr g))) (setq mod "Y")) ; y, Y (if (or (= 13 (cadr g))(= 32 (cadr g))) (setq endloop "Yes")) ; end loop marker ;;NUMBER ENTRY (if (and (< 48 (cadr g)) (< (cadr g) 57)) (progn (princ "\n")(princ (chr (cadr g))) (setq MyDist (atof (strcat (chr (cadr g)) (rtos (getreal)))))(princ "\n")(princ MyDist) ) ) ;;END NUMBER ENTRY (princ (strcat "\nPress \"X\" or \"Y\" [" mod "], select entities to stretch, or [ENTER] to exit: ")) ; change of mod ) ; end text entry cond ((= (car g) 3) ;;Set click (cond ; set / reset points ((= pt1 nil)(setq pt1 (cadr g))) ((= pt2 nil)(setq pt2 (cadr g))) ((= pt3 nil)(setq pt3 (cadr g))) ((= pt4 nil)(setq pt4 (cadr g))) ( T (setq pt1 nil)(setq pt2 nil)(setq pt3 nil)(setq pt4 nil)) ; reset points ) (if (setq MyEnt (car (nentselp pt1)) ) ; if single entity selected (progn (redraw MyEnt 3) (setq pt2 pt1) (princ (strcat "\nSingle Entity Selected.\nSpecify base point (or X, Y) [" mod "].")) ) ; end progn ) ; end if (if (and pt1 pt2 (not MyEnt)) (progn (if (< (car Pt1)(car Pt2)) ; L->R Selection (setq MySS (ssget "_W" Pt1 Pt2 )) ; Window selection (setq MySS (ssget "_C" Pt1 Pt2 )) ; crossing selection ) (redraw) (if MySS (progn (setq acount 0) (while (< acount (sslength MySS)) (redraw (ssname MySS acount) 3) (setq acount (+ acount 1)) ) ; end while MySS (princ (strcat "\nEntities Selected.\nSpecify base point (or X, Y) [" mod "].")) ) ; end progn (progn (setq pt1 nil)(setq pt2 nil)(setq pt3 nil)(setq pt4 nil) ) ) ; end if MySS ) ; end progn ) ; end if pt1, pt2, not MyEnt ) ; end click entry cond ((and pt1 (not pt2) (= (car g) 5) (not MyEnt) ) ; Draw selection rectangle (setq p3 (cadr g)) (setq p2 (list (car pt1) (cadr p3))) (setq p4 (list (car p3) (cadr pt1))) (redraw) (grvecs (list -256 pt1 p2 p2 p3 p3 p4 p4 pt1)) ) ) ; end conds ;;Single entity stretch ; (if (and pt2 MyEnt) (if (and pt3 MyEnt) (progn (princ "\nSpecify second point") (if (= mod "X") ; X or Y axis ; (command "_.stretch" MyEnt "" (mapcar '* '(1 0 0) pt2) (mapcar '* '(1 0 0) (setq pt3 (getpoint)))) ; (command "_.stretch" MyEnt "" (mapcar '* '(0 1 0) pt2) (mapcar '* '(0 1 0) (setq pt3 (getpoint)))) (command "_.stretch" MyEnt "" (mapcar '* '(1 0 0) pt3) (mapcar '* '(1 0 0) (setq pt4 (getpoint)))) (command "_.stretch" MyEnt "" (mapcar '* '(0 1 0) pt3) (mapcar '* '(0 1 0) (setq pt4 (getpoint)))) ) (redraw MyEnt 4) (setq pt1 nil)(setq pt2 nil)(setq pt3 nil)(setq pt4 nil) ; reset points (setq MyEnt nil)(setq MySS nil) ; reset entity selection (princ (strcat "Press \"X\" or \"Y\" [" mod "], select entities to stretch, or [ENTER] to exit: ")) ) ; end progn ) ; end if ;;Selection set stretch (if (and pt3 MySS) (progn (princ "\nSpecify second point") (if (= mod "X") ; X or Y axis (command "_.stretch" MySS "" (mapcar '* '(1 0 0) pt3) (mapcar '* '(1 0 0) (setq pt4 (getpoint)))) (command "_.stretch" MySS "" (mapcar '* '(0 1 0) pt3) (mapcar '* '(0 1 0) (setq pt4 (getpoint)))) ) (setq acount 0) ; remove highlights (while (< acount (sslength MySS)) (redraw (ssname MySS acount) 4) (setq acount (+ acount 1)) ) ; end while MySS (setq pt1 nil)(setq pt2 nil)(setq pt3 nil)(setq pt4 nil) ; reset points (setq MyEnt nil)(setq MySS nil) ; reset entity selection ) ; end progn ) ; end if ) ; end while grread (redraw) (command "regen") (princ "Ended OK")(princ) ) -EDIT- Added a quick number entry function to specify distance later Edited September 11 by Steven P 3 Quote
rlx Posted September 10 Posted September 10 That's a lot of (good) code Steven but still trying to wrap my mind around OP's request and if its academic or has any practical use. 1 Quote
3dwannab Posted September 11 Author Posted September 11 (edited) Thanks @Steven P, looks good so far. To give insight into my reasoning for this, is to lock either the X or Y axis to allow snapping to an endpoint only. I mocked up an example but I trust you that I use this in my day-to-day work. Edited September 11 by 3dwannab 1 Quote
rlx Posted September 11 Posted September 11 (edited) ok it makes more sense now Edited September 11 by rlx 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.