Jump to content

MullinRJ

Member
  • Posts

    2,004
  • Joined

  • Last visited

Posts posted by MullinRJ

  1. Hello @Lunar Waneshaft,

       Forgive me if I don't quite understand the question, so let me try to answer what I think you're asking.

     

       If you change the angle between the sides, you are effectively changing the number of sides around the circle. So at 10° between segments you have 36 sides, changing it to 7.5° will give you 360°/7.5°, or 48 sides.

     

       You can put 360/7.5 in the first field (# Sides) and 4800mm in the third field (Side Len), and click on the Apply button. Reshaper will calculate the number sides from the expression "360/7.5" and round the result to the nearest integer value. If you check the "Constant side length" checkbox, you can then change other fields and Reshaper will recalculate the Regular Polygon for you keeping the side length fixed – even with your units set to Ft and Inches, Reshaper will accept 4800mm and display it as 15'8.976" once you click the Apply button, but they are the same length.

     

       Whatever the Rotation Angle is when you click Apply will be your new reference angle, so make sure the red line denoting the radius is in the position you want or type a new angle in the Rotation field to set it. Also the anchor point, denoted by the red dot, will remain fixed in your drawing and all other points will expand or contract around it. In your case you have the Top of the circle anchored, so that point will remain fixed and everything else will move when you recalculate.

     

       If this isn't what you were looking for, please ask again, or PM me. I am open tomorrow and we can discuss over the phone if you like.

     

    Thanks for your comments. Very much appreciated.

    Raymond

    • Like 1
    • Love 1
  2. @Letti R beat me to the crux of the answer. 

     

    There is a caveat for using GetBBox. You need to adjust for the User Origin offset when on a Sheet Layer or inside a Symbol. When you are on Design Layers, you do not need to make the adjustment. So, you need to test for your location before calling GetBBox.

     

    Also, if you definitely only want to measure the FIRST SELECTED OBJECT, then leave your return value as "True", as it will stop after processing the first selected object.

     

    Raymond

     

     

    • Like 1
  3. On 4/27/2023 at 3:07 AM, Thomas W said:

    Is it possible to add a function that should escape and stop the running script?

     

    @Thomas W,

       To answer your last question, YES. There is a 4-Button pre-defined dialog you can use that gives you multiple options – AlertQuestion(). I modified your code (long version) to show how to use it, and am only using 3 of the buttons – for Delete, Skip, and Cancel. For more complicated user interactions you can build a custom dialog, but for what you want, this is quicker.

     

       In the following script, I added a { *** NEW *** } label after each line I added. Some lines were deleted, but I did not mark them. 

     

    PROCEDURE SearchDuplicateWall;
    { Utiliser ce script dans la vue en Plan 2D. }
    { ce script va chercher des murs qui ne seraient pas visibles en 2d et qui seraient cachés en étant sur des couches inférieures. }
    { Use this script in 2D Plan view. }
    { This script will look for walls which would not be visible in 2d and which would be hidden by being on lower layers. }
    
    CONST
    	kWallType = 68;		{ type objet mur }
    	kCR = chr(13);		{ Carriage Control char }
    	kSNameTemp = 'Tmp';
    
    VAR 
    	Hd1,  Hd2 :HANDLE;
    	Done :BOOLEAN;			{ *** NEW *** }
    	TL_A, BR_A, CenA :POINT;	{ BBox et points centraux pour A } { BBox & Center Points for A }
    					{ TL = TopLeft, BR = BottomRight, Cen = Center }
    	SWallStyleName, ActLName :STRING;
    	
    	
    	PROCEDURE CompareNextObjectWall(Hd2 :HANDLE); 
    	{ Recherche un mur avec la même boite englobante et le même centre. }
    	{ searches for a wall with the same bounding box and the same center. }
    	VAR
    		Choice :INTEGER;		{ *** NEW *** }
    		Question :STRING;
    		TL_B, BR_B, CenB :POINT;	{ BBox et points centraux pour B } { BBox & Center Points for B }
    	BEGIN
    		GetBBox(Hd2, TL_B.x, TL_B.y, BR_B.x, BR_B.y);
    		HCenter(Hd2, CenB.x, CenB.y);
    		IF (TL_A = TL_B) & (BR_A = BR_B) & (CenA = CenB) THEN 
    			BEGIN 
    				SetSelect(Hd2);
    				DoMenuTextByName('Fit To Objects', 0);
    				SetZoom(100);
    				SWallStyleName := GetWallStyle(Hd2);
    
    				{ Do you want to delete this Duplicate whose wall style is: }
    				Question := Concat('Voulez-vous supprimer ce Doublon dont le style de mur est :  ', SWallStyleName);
    
    				Choice := AlertQuestion(Question, '', 1, 'Delete', 'Cancel', 'Skip', '');	{ *** NEW *** }
    				CASE Choice of					{ *** NEW *** }
    					1: DelObject(Hd2);	{ Delete }	{ *** NEW *** }
    					2: SetDSelect(Hd2);	{ Skip }	{ *** NEW *** }
    					0: Done := TRUE;	{ QUIT }	{ *** NEW *** }
    				END;		{ CASE }			{ *** NEW *** }
    
    		END;		{ if BBox & Cen are equal }
    	END;		{ CompareNextObjectWall }
    
    
    	PROCEDURE CompareHiddenWall(Hd2 :HANDLE); 
    	{ Recherche un mur qui serait caché dans l'alignement d'un autre mur sans avoir forcément la même taille. }
    	{ searches for a wall that would be hidden in line with another wall without necessarily having the same size. }
    	VAR
    		Choice :INTEGER;	{ *** NEW *** }
    		Question :STRING;
    		CenB :POINT;		{ points centraux pour B } { Center Points for B }
    	BEGIN
    		HCenter(Hd2, CenB.x, CenB.y);
    		IF (((CenB.x = CenA.x) & (CenB.y <= TL_A.y) & (CenB.y >= BR_A.y)) | ((CenB.y = CenA.y) & (CenB.x >= TL_A.x) & (CenB.x <= BR_A.x))) THEN
    			BEGIN 
    				SetSelect(Hd2);
    				DoMenuTextByName('Fit To Objects', 0);
    				SetZoom(100);
    				SWallStyleName := GetWallStyle(Hd2);
    			
    				{ Do you want to delete this Hidden Wall whose wall style is: }
    				Question := Concat('Voulez-vous supprimer ce Mur Caché dont le style de mur est :  ', SWallStyleName);
    				Choice := AlertQuestion(Question, '', 1, 'Delete', 'Cancel', 'Skip', '');	{ *** NEW *** }
    				CASE Choice of					{ *** NEW *** }
    					1: DelObject(Hd2);	{ Delete }	{ *** NEW *** }
    					2: SetDSelect(Hd2);	{ Skip }	{ *** NEW *** }
    					0: Done := TRUE;	{ QUIT }	{ *** NEW *** }
    				END;		{ CASE }			{ *** NEW *** }
    			END;		{ IF }
    	END;		{ CompareHiddenWall }
    
    
    BEGIN
    	DSelectAll;
    	Hd1 := LActLayer;
    	ActLName := GetLName(ActLayer);
    	Done := False;				{ *** NEW *** }
    	WHILE not Done & (Hd1 <> NIL) DO	{ *** NEW *** }
    		BEGIN
    			IF (GetTypeN(Hd1) = kWallType) THEN
    				BEGIN
    					GetBBox(Hd1, TL_A.x, TL_A.y, BR_A.x, BR_A.y);
    					HCenter(Hd1, CenA.x, CenA.y);
    					DelName(kSNameTemp);
    					SetName(Hd1, kSNameTemp);
    					ForEachObject(CompareNextObjectWall,  (NOTINDLVP & NOTINREFDLVP & ((L=ActLName) & (T=WALL) & (N<>kSNameTemp))));
    					DelName(kSNameTemp);
    				END;		{ IF }
    			Hd1 := PrevObj(Hd1);
    		END;		{ WHILE }
    	if not Done then		 { *** NEW *** }
    		AlrtDialog('Il n''y a pas ou plus de "Doublon" de mur en arrière plan');	{ There is no or no more "Duplicate" wall in the background }
    	
    	Hd1 := LActLayer;
    	{ Enable next line if you want to be able to cancel each loop separately. }
    {	Done := False;	} 		  { *** NEW *** }
    	WHILE not Done & (Hd1 <> NIL) DO  { *** NEW *** }
    		BEGIN
    			IF (GetTypeN(Hd1) = kWallType) THEN
    				BEGIN
    					GetBBox(Hd1, TL_A.x, TL_A.y, BR_A.x, BR_A.y);
    					HCenter(Hd1, CenA.x, CenA.y);
    					DelName(kSNameTemp);
    					SetName(Hd1,  kSNameTemp);
    					ForEachObject(CompareHiddenWall,  (NOTINDLVP & NOTINREFDLVP & ((L=ActLName) & (T=WALL) & (N<>kSNameTemp))));
    					DelName(kSNameTemp);
    				END;		{ IF }
    			Hd1 := PrevObj(Hd1);
    		END;		{ WHILE }
    	if not Done then		{ *** NEW *** }
    		AlrtDialog('Il n''y a pas ou plus de Murs cachés en arrière plan');		{ There are no or no more hidden walls in the background }  
    END;
    Run(SearchDuplicateWall);

     

       If you have any questions, someone is always here.

     

    Raymond

     

     

    • Love 1
  4. Hello @Thomas W,

       Everything you've written is good. It works and the flow is straight forward. I can only offer very minor suggestions, which you can follow or ignore. They may make your future scripts easier to read later, after you've forgotten how you solved a problem.

     

       First, your variable names are nondescript. I changed the variable names to better reflect what they mean. For your BoundingBox vars, you used: A1x,A1y,A2x,A2y, CAx,CAy :REAL; I changed them to: TL_A, BR_A, CenA :POINT; where TL = TopLeft, and BR = BottomRight. Each POINT variable has an X & Y component built in. Where you had 6 variables now there are 3. Consider it a package deal. Type VECTOR gives you a 3-way bundle with XY&Z components. This can reduce clutter for you, and for anyone you are sharing your code with. 

     

       Second, I replaced your boolean operators, AND and OR, with & and |. These are short circuit operators that do the same thing, but evaluation of the boolean expression stops when the outcome is decided. If A is FALSE, you don't need to evaluate B in the expression (A & B), because B cannot affect the outcome. Likewise for the expression (A | B), if A is TRUE, B does not affect the outcome. If you want to know more about this, just ask. There are other subtleties.

     

       I also changed your temp class name, and the CR character (chr(13)), to constants; and I moved your PrefObj() calls outside the IF structures, for style reasons only. 

     

       Lastly, because I spotted it just before I hit submit, I changed the way you coded your active layer name in your search criteria. Currently, your script only works on the hard coded layer 'Dessin'. In another file your layer names will most likely be different, or you may want to run the script on multiple layers in the same file. By assigning the Active Layer name to a string variable, you can use the <criteria> statement in this script pretty much the way you wrote it, but now (L=ActLName) will replace (L='Dessin'), and you won't have to edit your script to run it elsewhere. It will always run on the active design layer.

     

       If you do nothing else, your script looks like this:

    PROCEDURE SearchDuplicateWall;
    { Utiliser ce script dans la vue en Plan 2D. }
    { ce script va chercher des murs qui ne seraient pas visibles en 2d et qui seraient cachés en étant sur des couches inférieures. }
    { Use this script in 2D Plan view. }
    { This script will look for walls which would not be visible in 2d and which would be hidden by being on lower layers. }
    
    CONST
    	kWallType = 68;		{ type objet mur }
    	kCR = chr(13);		{ Carriage Control char }
    	kSNameTemp = 'Tmp';
    
    VAR 
    	Hd1,  Hd2 :HANDLE;
    	TL_A, BR_A, CenA :POINT;	{ BBox et points centraux pour A } { BBox & Center Points for A }
    					{ TL = TopLeft, BR = BottomRight, Cen = Center }
    	SWallStyleName, ActLName :STRING;
    	
    	
    	PROCEDURE CompareNextObjectWall(Hd2 :HANDLE); 
    	{ Recherche un mur avec la même boite englobante et le même centre. }
    	{ searches for a wall with the same bounding box and the same center. }
    	VAR
    		TL_B, BR_B, CenB :POINT;	{ BBox et points centraux pour B } { BBox & Center Points for B }
    	BEGIN
    		GetBBox(Hd2, TL_B.x, TL_B.y, BR_B.x, BR_B.y);
    		HCenter(Hd2, CenB.x, CenB.y);
    		IF (TL_A = TL_B) & (BR_A = BR_B) & (CenA = CenB) THEN 
    			BEGIN 
    				SetSelect(Hd2);
    				DoMenuTextByName('Fit To Objects', 0);
    				SetZoom(100);
    				SWallStyleName := GetWallStyle(Hd2);
    
    				{ Do you want to delete this Duplicate whose wall style is: }
    				IF YNDialog(Concat('Voulez-vous supprimer ce Doublon dont le style de mur est :', kCR, SWallStyleName)) THEN
    					DelObject(Hd2)
    				ELSE
    					SetDSelect(Hd2);
    			END;		{ if BBx & Cen are equal }
    	END;		{ CompareNextObjectWall }
    
    
    	PROCEDURE CompareHiddenWall(Hd2 :HANDLE); 
    	{ Recherche un mur qui serait caché dans l'alignement d'un autre mur sans avoir forcément la même taille. }
    	{ searches for a wall that would be hidden in line with another wall without necessarily having the same size. }
    	VAR
    		CenB :POINT;		{ points centraux pour B } { Center Points for B }
    	BEGIN
    		HCenter(Hd2, CenB.x, CenB.y);
    		IF (((CenB.x = CenA.x) & (CenB.y <= TL_A.y) & (CenB.y >= BR_A.y)) | ((CenB.y = CenA.y) & (CenB.x >= TL_A.x) & (CenB.x <= BR_A.x))) THEN
    			BEGIN 
    				SetSelect(Hd2);
    				DoMenuTextByName('Fit To Objects', 0);
    				SetZoom(100);
    				SWallStyleName := GetWallStyle(Hd2);
    			
    				{ Do you want to delete this Hidden Wall whose wall style is: }
    				IF YNDialog(Concat('Voulez-vous supprimer ce Mur Caché dont le style de mur est :', kCR, SWallStyleName)) THEN
    					DelObject(Hd2)
    				ELSE
    					SetDSelect(Hd2);
    			END;
    	END;		{ CompareHiddenWall }
    
    
    BEGIN
    	DSelectAll;
    	Hd1 := LActLayer;
    	ActLName := GetLName(ActLayer);
    	WHILE (Hd1 <> NIL) DO
    		BEGIN
    			IF (GetTypeN(Hd1) = kWallType) THEN
    				BEGIN
    					GetBBox(Hd1, TL_A.x, TL_A.y, BR_A.x, BR_A.y);
    					HCenter(Hd1, CenA.x, CenA.y);
    					DelName(kSNameTemp);
    					SetName(Hd1, kSNameTemp);
    					ForEachObject(CompareNextObjectWall,  (NOTINDLVP & NOTINREFDLVP & ((L=ActLName) & (T=WALL) & (N<>kSNameTemp))));
    					DelName(kSNameTemp);
    				END;
    			Hd1 := PrevObj(Hd1);
    		END;
    	AlrtDialog('Il n''y a pas ou plus de "Doublon" de mur en arrière plan');	{ There is no or no more "Duplicate" wall in the background }
    	
    	Hd1 := LActLayer;
    	WHILE (Hd1 <> NIL) DO
    		BEGIN
    			IF (GetTypeN(Hd1) = kWallType) THEN
    				BEGIN
    					GetBBox(Hd1, TL_A.x, TL_A.y, BR_A.x, BR_A.y);
    					HCenter(Hd1, CenA.x, CenA.y);
    					DelName(kSNameTemp);
    					SetName(Hd1,  kSNameTemp);
    					ForEachObject(CompareHiddenWall,  (NOTINDLVP & NOTINREFDLVP & ((L=ActLName) & (T=WALL) & (N<>kSNameTemp))));
    					DelName(kSNameTemp);
    				END;
    			Hd1 := PrevObj(Hd1);
    		END;
    	AlrtDialog('Il n''y a pas ou plus de Murs cachés en arrière plan');		{ There are no or no more hidden walls in the background }  
    END;
    Run(SearchDuplicateWall);

     

     

    If you consolidate your two subroutines into one, to remove Duplicate and Hidden walls at the same time, your script could look something like this:

    PROCEDURE SearchDuplicateWall;
    { Utiliser ce script dans la vue en Plan 2D. }
    { ce script va chercher des murs qui ne seraient pas visibles en 2D et qui seraient cachés en étant sur des couches inférieures. }
    { Use this script in 2D Plan view. }
    { This script will look for walls which would not be visible in 2D and which would be hidden by being on lower layers. }
    
    CONST
    	kWallType = 68;		{ type objet mur } { wall object type }
    	kCR = chr(13);		{ Carriage Control char }
    	kSNameTemp = 'Tmp';
    
    VAR 
    	Hd1, Hd2 :HANDLE;
    	SWallStyleName, ActLName :STRING;
    	TL_A, BR_A, CenA :POINT;	{ BBox et points centraux pour A } { BBox & Center Points for A }
    					{ TL = TopLeft, BR = BottomRight, Cen = Center }
    	
    	
    	PROCEDURE CompareWalls(Hd2 :HANDLE); 
    	{ recherche un mur qui serait caché dans l'alignement d'un autre mur sans avoir forcément la même taille }
    	{ searches for a wall that would be hidden in line with another wall without necessarily having the same size }
    	VAR
    		CondA, CondB, CondC :BOOLEAN;	{ conditions booléennes } { boolean conditions }	
    		TL_B, BR_B, CenB :POINT;	{ BBox et points centraux pour B } { BBox & Center Points for B }
    		Question :String;
    	BEGIN
    		GetBBox(Hd2, TL_B.x, TL_B.y, BR_B.x, BR_B.y);
    		HCenter(Hd2, CenB.x, CenB.y);
    	
    		CondA := (TL_A = TL_B) & (BR_A = BR_B) & (CenA = CenB);			{ duplicate walls }
    		CondB := (CenB.x = CenA.x) & (CenB.y <= TL_A.y) & (CenB.y >= BR_A.y);	{ vertical hidden walls }
    		CondC := (CenB.y = CenA.y) & (CenB.x >= TL_A.x) & (CenB.x <= BR_A.x);	{ horizontal hidden walls }
    	
    		IF CondA | CondB | CondC THEN
    			BEGIN
    				SetSelect(Hd2);
    				DoMenuTextByName('Fit To Objects', 0);
    				SetZoom(100);
    				SWallStyleName := GetWallStyle(Hd2);
    			
    							{ Do you want to delete this Duplicate whose wall style is }
    				IF CondA THEN Question := 'Voulez-vous supprimer ce Doublon dont le style de mur est: '	
    							{ Do you want to delete this Hidden Wall whose wall style is }
    				ELSE Question := 'Voulez-vous supprimer ce Mur Caché dont le style de mur est: ';		
    				IF YNDialog(Concat(Question, '  —  ', SWallStyleName)) 
    					THEN DelObject(Hd2)
    					ELSE SetDSelect(Hd2);
    			END;
    	END;		{ CompareWalls }
    
    
    BEGIN
    	DSelectAll;
    	Hd1 := LActLayer;
    	ActLName := GetLName(ActLayer);
    	WHILE (Hd1 <> NIL) DO
    		BEGIN
    			IF (GetTypeN(Hd1) = kWallType) THEN
    				BEGIN
    					GetBBox(Hd1, TL_A.x, TL_A.y, BR_A.x, BR_A.y);
    					HCenter(Hd1, CenA.x, CenA.y);
    					DelName(kSNameTemp);
    					SetName(Hd1, kSNameTemp);
    					ForEachObject(CompareWalls, (NOTINDLVP & NOTINREFDLVP & (L=ActLName) & (T=WALL) & (N<>kSNameTemp)) );
    					DelName(kSNameTemp);
    				END;		{ if }
    			Hd1 := PrevObj(Hd1);
    		END;		{ while }
    	{ There is no or no more "Duplicate" wall in the background }
    	{ AND }
    	{ There are no or no more hidden walls in the background }  
    	AlrtDialog(concat('Il n''y a pas ou plus de "Doublon" de mur en arrière plan', kCR, 'ET', kCR,
    			'Il n''y a pas ou plus de Murs cachés en arrière plan'));				
    END;
    Run(SearchDuplicateWall);

     

     

       Honestly, none of these changes are necessary. Everything you've written is fine, and the modified scripts work identically to yours.

     

       The only thing I would recommend you do differently is add more comments as you script. It will help you down the road when you revisit your scripts. Consider if this script was 1000 lines, or lots more, instead of ~100 lines. Comments will save you a lot of confusion and headaches later on.

     

    HTH,

    Raymond

     

    • Like 1
  5. No, not all menu items can be called by DoMenuTextByName(). Sorry. And the documentations is also incomplete. What functions are you trying to use? 

     

    If after trying what you think should work, and any variation of that command that seems reasonable and your attempts don't succeed, check back to this Forum. You will probably get a very quick confirming answer from someone who has tried before. If you are really lucky, you will get the name of a command that will work. 

     

    All the best,

    Raymond

    • Like 1
  6. @michaelk,

       If you are using "Case ________ of" then you must be using VectorScript, in which case you'd use (borrowing from @Julian Carr's example above):

    	...
    	vsoGetEventInfo(theEvent, theData);
    
    	case theEvent of
    
    		{ other events here }
    
    		60: BEGIN { Edit Plug-in Style }
    			vsoSetEventResult( -10 ); {kObjectEventHandled} { using -10 here causes the object properties dialogue to open next }
    		END;
    
    		61: BEGIN { Create Plugin Style }
    			vsoSetEventResult( 0 ); {kObjectEventHandled}
    		END;
    
    		62: BEGIN { Update Styled Plugin Object }
    			vsoSetEventResult( 0 );
    		END;
    
    		63: BEGIN { Finalize Create Style }
    			vsoGetPluginStyleSym(gh1);
    			SetAllStyleParams(gh1, 0); { this sets all parameters to not use the style }
    			vsoSetEventResult( 0 );
    		END;
    
    		64: BEGIN { Finalize Update Styled Object }
    			vsoSetEventResult( -8 );
    		END;
    
    		65: BEGIN { Style Widget Chosen }
    			vsoSetEventResult( 0 );
    		END;
    		{ Create Style order of events: 61, 63, 60, 62, 64 }
    		{ Edit Style order of events: 60, 62, 64 }
    
    
    		{ more "other events" here }
    
    	end;		{ case theEvent }

     

       If you are using Python, there is no "CASE" statement, so you'll have to use an "IF" tree.

     

    HTH,

    Raymond

     

  7. Have you tried:

     

    def  vs.GetCustomObjectProfileGroup( objectHand )

       return HANDLE

     

    where objectHand can be a handle to a PIO object in the drawing when your script executes outside of PIOs, and objectHand can be gPio_H (from your example above) when your script is the PIO script?

     

    Raymond

  8. Asking for two input parameters may be a mistake, but it may also work as defined if the second parameter is sometimes an input parameter. Some input parameters will accept NIL (or None) as valid input and report differently from passing in a non-NIL value. Again, I'm guessing here as I've never used the function. If it works as you've shown, then use it. Keep notes for future reference. You never know if, or when, things may change. 

     

    Raymond

  9. Hello @Gregi,

       Though I haven't used either command it appears the first, vs.vsoGetPluginStyleSym(), is used to reference itself and return the Symbol Definition linked to its STYLE definition. Its description says: "Allow an object to use its own implementation in creating and maintaining a plugin style." It must be used inside the PIO code, as indicated by the first three letters in the command name "vso".

     

       The second command, vs.GetPluginStyleSymbol(), appears to be used outside a PIO, as in a script that queries PIO objects, and it will return TRUE if the object is STYLED, and FALSE if it isn't. If it returns TRUE, it will also return a handle to the symbol that's used to define its STYLE.

     

       The best way to see what they do is to try them in simple scripts. Place a STYLED PIO in a drawing and write a short script with:

    Boo, SymHnd = vs.GetPluginStyleSymbol(FSActLayer) to see what it returns. Message out the boolean result, and the object type and symbol name of the returned handle.

     

       The vso command will require more setup to test its functionality, but if you are developing a STYLED PIO, place vs.GetPluginStyleSym() in your PIO script and set an AlrtDialog() with the object type and symbol name of the returned handle to see what comes out. You may have to move the command around so that it executes in the proper event and at the proper time.

     

       If this is not clear, wait for better answers. I'm sure they are out there.

     

    Raymond

  10. @bsalee,

       If you only want assign a static class name, the script is easy. But if you want to be able to redefine a new Class Name often, the script will need to be more complicated. You can edit this script, or have multiple copies of it in your file, each with a different class name to set commonly used class names. If the class name in this script does not exist in your file, it will be created so you won't have to create it ahead of time.

     

       For starters, place the following script in one of your files by adding it to a Script Palette (new or existing). Duplicate it if you want a choice of class names. If you like how it works, you can add this script(s) to your template files so it(they) will always be there when you start new work; or make a Menu Command plug-in, where you can assign a HotKey to it; or make a Tool plug-in, which can also have an assigned HotKey. More on the second and third options when you get that far.

     

    Here's the simple script:

     

    PROCEDURE ChangeDimClassName;
    { Click on Dimension objects to change their class to the class name defined in "kNewClass". }
    { Change constant "kNewClass" to suit your needs. }
    { If the object you select is not a Dimension object, nothing happens and program continues. }
    { To STOP, click in empty drawing space, or press any key on keyboard. }
    { 9 Apr 2023 - Raymond Mullin }
    CONST
    	kNewClass = 'New Dim Class';
    	kDimType = 63;
    VAR
    	H :Handle;
    	X, Y :Real;
    BEGIN
    	H := FObject;	{ dummy handle }
    	while (H <> nil) do begin
    		GetPt(X, Y);
    		H := PickObject(X, Y);
    		if (GetTypeN(H) = kDimType) then
    			SetClass(H, kNewClass);
    	end;		{ while }
    END;
    Run(ChangeDimClassName);

     

    HTH,

    Raymond

     

  11. @bsalee, Could you please explain in a little more detail what you want to happen?

     

    Are you referring to this setting in the Document Preferences, as the dimension class name you want to assign?

    677273251_DocPrefDimClass.jpg.e0325d33890a0eac4039e6ebc01477e4.jpg

     

    Or, are you wanting to assign another class to dimensions that you click on?

     

    Or, do you want to toggle that Document Preference ON and OFF? 

     

    It is possible to set it up as either a TOOL, or a SCRIPT, but there are some nuances in the way each functions. More detail will help. If you could clarify your request a bit, I or someone else might be able to help. 

     

    Thank you,

    Raymond

  12. Pref 44 is shorthand for VW Application Preference 44. It is a boolean flag, meaning it has a value of True or False.

     

    Use Boo := GetPref(44); to read the value into boolean variable "Boo", SetPref(44, True); to set the flag, and SetPref(44, False); to clear the flag.

    The results of these commands can be seen in the Document Preferences dialog. The checkbox will change states with this Pref 44 value, or vice versa.

     

    1665175958_DocPrefs.png.7a3aa288e0fbee93a16cd00e5b9142b2.png

     

    Pref 546 is in the newer versions of VW and you would use L := GetPrefLongint(546); to read it into variable "L", which you define as a LONGINT. 

     

    Poof – You are now in the Cult. Drink the KoolAid and Smile  😁

    Next Week we'll explore Toggle Scripts.

     

    Raymond

    • Like 1
  13. @Jiajing,

       I can confirm that @Pat Stanford is correct, in that the options for all of the FEOIL commands can be added together to give you combined attributes. In this case your Layer Options = 3 does in fact mean All Layers AND Visible Layers, which reduces to All Layers. Often, I'll use 3 in the Object Options to get me Visible AND Selected objects.

     

       It is possible to make ForEachObjectInLayer() act like FSActLayer if you return True from your "todo" function. When True is returned, processing stops. Returning nothing defaults to False, and all objects within the scope of the command get processed.

     

       Here's a variation of your script that shows all of the pertinent information in one Alert Dialog, including the object type number. I would recommend changing the last option to a 4, to only work on Editable layers. This avoids grabbing objects on Gray or Hidden layers.

    import vs
    CR = chr(13)	# Carriage Return char
    
    def todo(h):
    	p = vs.GetBBox(h)
    	vs.AlrtDialog('BBox for Obj Type: ', vs.GetTypeN(h), CR, 'TL: ', p[0][0], ',  ', p[0][1], CR, 'BR: ', p[1][0], ',  ', p[1][1])
    	return True
    	
    vs.ForEachObjectInLayer(todo,2,0,3) # Selected, Shallow, All & Visible layers

     

       And here's a simpler version of the same script, using vs.FSActLayer() (as Pat recommended.) This style of script is primarily used when you are working only on the Active Layer.

    import vs
    CR = chr(13)	# Carriage Return char
    
    h = vs.FSActLayer()
    p = vs.GetBBox(h)
    vs.AlrtDialog('BBox for Obj Type: ', vs.GetTypeN(h), CR, 'TL: ', p[0][0], ',  ', p[0][1], CR, 'BR: ', p[1][0], ',  ', p[1][1])

     

    Note: I always place a comment after the FEOIL commands to spell out the numeric meanings of the options. Unless your memory is perfect, this will save you tons of time in the future when you revisit your scripts so you don't have to relook up the command to find out what the numbers mean — again.

     

    HTH,

    Raymond

    • Like 1
  14. 7 minutes ago, Pat Stanford said:

    I agree on the Pref 44. But I think the Class will change no matter the setting of 44. It just won't auto class the dims.

     

    I'm not sure we're saying the same thing, but we may be.

     

    If Pref 44 is FALSE, dimensions go into the ACTIVE CLASS. 

    Else, when Pref 44 is TRUE, dimensions go into the class defined by Pref 546, i.e. the Default Dimension Class.

     

    So, if you want to toggle between the "Dimension" class and the Active Class, you only need to toggle Pref 44. However, if you want to toggle between "ClassA" , and "ClassB" then a script like yours will work, but to be sure it does, you should also check and set Pref 44, because if it is ever FALSE, your script will mysteriously fail to work. I know, that's unlikely, but not impossible.

     

    Raymond 

    • Like 2
  15. Hi Sam,

       You have the 1st five correct.

     

    Short is an integer, so use Get/SetObjectVariableInt.

    Sint32 is a Longint, so use Get/SetObjectVariableLongInt.

    The "RefNumber" shown above are type Sint32 (Longint) - see previous line.

    I'm guess on the "void write" entries, but judging from their ovNames, they may be BOOLEAN, but you can only write to then, and not read them. 

    Not sure how to read or write a transform matrix from VS.

    • Like 1
  16. Oh, Pat, you are crazy ...rational AND crazy... but you know what they say, it takes one to know one. 😉 

     

    Here ya' go. Here's my Secret Sauce recipe. Cut and Paste to your heart's delight.

     

    Procedure ListHiddenRecordFormats;
    CONST	CR = chr(13);
    VAR	S1 :DynArray of Char;
    
    	Procedure HiddenRecordNames(var S1 :Dynarray of Char);
    	{ Append the names of all Hidden Records to text block S1. }
    	{ 25 Mar 2023 - Raymond J Mullin }
    	Const
    		RecordType = 47;
    		DummyRec = 'DummyRec';
    		DummyFld = 'DummyFld';
    	Var
    		hndDummyRec, RecHnd :Handle;
    	Begin
    		NewField(DummyRec, DummyFld, '1', 3, 0);		{ create dummy record }
    		hndDummyRec := GetObject(DummyRec);			{ get handle to new record }
    		SetObjectVariableBoolean(hndDummyRec, 900, False);	{ hide it }
    		RecHnd := NextObj(hndDummyRec);				{ get handle to next object on list }
    		DelObject(hndDummyRec);					{ not needed any more }
    		while (RecHnd <> nil) do begin				{ traverse the Hidden Record list }
    			if (GetType(RecHnd) = RecordType) then
    				S1 := concat(S1, GetName(RecHnd), CR);
    			RecHnd := NextObj(RecHnd);			{ Next Object on list }
    		end;		{ while }
    	End;		{ HiddenRecordNames }
    
    BEGIN
    	S1:='The file contains the following hidden record formats:';
    	S1:=Concat(S1, CR, CR);
    
    	HiddenRecordNames(S1);		{ append Hidden Record Names to text block }
    	
    	S1:=Concat(S1,'*****');	
    	AlrtDialog(S1);
    END;
    Run(ListHiddenRecordFormats);

     

    Raymond

    • Like 1
  17. 2 hours ago, Pat Stanford said:

    What am I missing?

    Hey Pat,

       Hmmmmm, the secret sauce?

     

       I don't know why BuildResourceList() does not see Hidden Records, but judging from your example, it obviously doesn't. That said, I vaguely remember (meaning some old code I wrote shows) that Hidden Records are kept in a different list from the other records. The only way I can think of right now is to search that other list and use AddResourceToList() to place the Hidden Records into your list.

     

       Are you wanting your Resource List to contain only Hidden Records, All Records, or a mixture (Visible, PIO, Hidden)? I don't have a code sample to cut and paste right now because I wasn't using Resource Lists at the time, but I can mock one up shortly.

     

    Raymond

     

  18. @WhoCanDo,

       I just placed your script into a Menu Command, placed that command in my Custom Menu, and assigned Cmd-Shift-9 to it. It works without the extra overhead of having to click in the drawing. I think that initial click is a built in penalty required when using tools vs. menu commands. You have to click in the drawing for the script to run. If using a hotkey for a menu command instead of a tool does not rail against the tenets of your core beliefs, may I recommend giving it a try to see if it will work for you?

     

    HTH,

    Raymond

  19. SP3 or SP4? I just remembered there was a bug in SP3 where the ALT keys for tools did not work. It seems to be fixed in SP4. If you're still on SP3, I recommend you upgrade to SP4.

     

    I'm using SP4 with OPT-9 set to your New Round Wall tool. When I press OPT-9 it almost sets the tool up, as the name shows in the Tool Bar, but none of the button icons appear. After I click once in the drawing, then the tool's mode buttons appear. When I click the second time I can draw with the New Round Wall tool. 

     

    I'm on a Mac, so the behavior may be different on your PC, but it's still not working the way I expected to. Can you describe in more detail what's happening your end?

     

    Raymond

×
×
  • Create New...