Jump to content

what is the workflow for ensuring that drawing objects stay in the correct class?


grant_PD

Recommended Posts

24 minutes ago, Jesse Cogswell said:

@michaelk I noticed in your screenshot that the two columns UUID and Parent UUID are visible.  These are supposed to be hidden (have a column width of 0), did you expand the columns or is that how it presents on Mac?  I'm asking because this plug-in will also use a hidden column to conceal the record name for each plug-in object so that it instead presents the localized name.  If the Record Name column is visible when you run this, let me know and I'll change up how the programming works a little bit.

I really hesitate to tell you this, but…. 

 

The slight offset in the column headers in the header row and in the body between Object Type and # in drawing that you see in Windows is more offset in Mac.  I can see the R in Record.

 

This is just going to make me go back over all your other menu commands and try to move columns around.

Link to comment

I've added this ability, but I did notice a fun bug when it comes to Callouts.  The script technically works but the new attributes won't show up on the callout until you use the Attribute Palette to change something.  None of the usual tricks to force a reset work, changing the Callout's layer, changing a parameter, or moving the object around.  If you change the Callout's class after the fact it will take on the attributes of the new class but I could not get it to work within a single run of the script.

 

I know you probably want this to work on Callouts since they're probably one of your most mis-classed objects, but there doesn't seem to be a solution with a script at the moment.  Even running the command twice, once to set attributes by class and again to set the new class, didn't work.  This is true at least for VW2019, 2023, and 2024 on Windows.  It might work properly on Mac.

 

Callout in the None class with no By Class attributes:

image.thumb.png.d91a9093fcfee4301ac744542e494eaf.png

 

Running the command:

image.png.a401879029189ebd89afa5cccfb9d162.png

 

After running the command, the only attribute that "stuck" is the fill pattern:

image.thumb.png.cbd0b6ec9ed5ae70b8910fc6f6ebb902.png

 

Changing parameters, layer, and even the note contents has no effect:

image.thumb.png.e16993be6cf31d7ec5508d226e2c30c0.png

 

Selecting the note and using the Attribute Palette "Make All Attributes By Class" button:

image.thumb.png.826798829497a4704baa59e216bd5981.png

 

This seems to be a bug with the Callout tool itself.  I tried a simple script that would set the pen color of any selected object to magenta and it works fine on everything except Callouts.  Neat.

 

Anyhow, updated plug-in is attached.  Save it over the existing one in your User Folder and restart Vectorworks.

Reset Plug-in Obj Classes.vsm

Link to comment
27 minutes ago, Jesse Cogswell said:

None of the usual tricks to force a reset work, changing the Callout's layer, changing a parameter, or moving the object around.  If you change the Callout's class after the fact it will take on the attributes of the new class but I could not get it to work within a single run of the script.

Have you tried the Reset All Plug-in Object command from the Tools:Utilities menu?  That should make them reset. And if you are only doing it occasionally after running the Classing PIO, then the delay should be tolerable.

Link to comment
2 hours ago, Pat Stanford said:

Have you tried the Reset All Plug-in Object command from the Tools:Utilities menu?  That should make them reset. And if you are only doing it occasionally after running the Classing PIO, then the delay should be tolerable.

 

Just tried it in both VW2019 and VW2024, no change on the Callout object.  I'm assuming that the menu command just runs on ResetObject on every object in the drawing (something along the lines of ForEachObject(ResetObject,(INSYMBOL & INVIEWPORT & (ALL)));), so it has the same effect as my script since it contains a ResetObject command as part of the execution.

 

The test that I just did looked like this:

 

Initial Setup

image.thumb.png.4a0a4655dacd0ef0972e54300f0f5490.png

After running the script:

image.thumb.png.03492fb6203de32f902099142988ba68.png

 

After running Tools - Utilities - Reset All Plug-ins:

image.thumb.png.2f930b80dc2bf6a9965da78cadbffbdb.png

 

No change.  That test script looks like this:

 

SetPenFore(FSActLayer,65535,0,65535);
SetPenBack(FSActLayer,65535,0,65535);

ResetObject(FSActLayer);
ReDrawAll;

 

Link to comment

Callouts are not normal.

 

Here's a script that changes a text object to a callout.  You would think that to create a callout you just CreateCustomObject('Callout',…. Then write some data to the record and Bob's your uncle.

 

Nope.

 

Take a look at how attributes are handled inside of what looks like comments.

 

PROCEDURE Test;

VAR
	hCallout,hText,Waldo : HANDLE;
	
	tempHandle, objectHandle, textHandle:HANDLE;
	objectName:STRING;
	index:INTEGER;

	s1 : DYNARRAY[] of CHAR;
	
	fakeName : STRING;
	
	objType : INTEGER;
	
	xx,yy,zz : REAL;
	
	
BEGIN;	
	Locus(0,0);
	Waldo := LNewObj;
	
	hText := PrevSObj(Waldo);
	DelObject(Waldo);
	HCenter(hText,xx,yy);
	fakeName := Date(2,1);
	SetName(hText,fakeName);

	objType := ObjectType(N = fakeName);

	IF objType = 10 
	THEN
		BEGIN
			{AlrtDialog(CONCAT('Objecty Type: ',objtype));}

			s1 := GetText(hText);

			{AlrtDialog(s1);}
tempHandle := CreateCustomObject('Callout',0",0",#0.0000000000000d);

objectHandle := LNewObj;
SetDropShadowData(objectHandle, 0,0.003937,0.001969,#315.0000000000d,75,0,0,0);
EnableDropShadow(objectHandle, FALSE);

objectHandle := LNewObj;
{SetObjectVariableBoolean(objectHandle, 1160, FALSE);}

Record(LNewObj,'Callout');
SetRField(LNewObj,'Callout','Link To Database','False');
SetRField(LNewObj,'Callout','Place As Keynote','False');
SetRField(LNewObj,'Callout','Keynote Prefix','');
SetRField(LNewObj,'Callout','Keynote Suffix','');
SetRField(LNewObj,'Callout','BubbWidth','2"');
SetRField(LNewObj,'Callout','Vertical Placement','Auto');
SetRField(LNewObj,'Callout','Orientation','Auto');
SetRField(LNewObj,'Callout','Left','False');
SetRField(LNewObj,'Callout','Bubble Style','None');
SetRField(LNewObj,'Callout','Radius Factor','0.046850393700787"');
SetRField(LNewObj,'Callout','Margin','0.046850393700787"');
SetRField(LNewObj,'Callout','Bubble Shadow','False');
SetRField(LNewObj,'Callout','Shoulder','1''0.000000000000002"');
SetRField(LNewObj,'Callout','Leader Type','Straight');
SetRField(LNewObj,'Callout','Leader Style','Line');
SetRField(LNewObj,'Callout','LineLength','7''2.331410057273573"');
SetRField(LNewObj,'Callout','__ShowDialog','False');
SetRField(LNewObj,'Callout','Rise','0.19"');
SetRField(LNewObj,'Callout','Text',S1);
SetRField(LNewObj,'Callout','DNE','Solid Arrow\1\-1');
SetRField(LNewObj,'Callout','TextFont','Arial');
SetRField(LNewObj,'Callout','TextSize','203.200000');
SetRField(LNewObj,'Callout','TextStyle','Plain');
SetRField(LNewObj,'Callout','ControlPoint01X','-1''7.526018289463835"');
SetRField(LNewObj,'Callout','ControlPoint01Y','-1''11.734217624645211"');
SetRField(LNewObj,'Callout','ControlPoint02X','-4''7.239175964666458"');
SetRField(LNewObj,'Callout','ControlPoint02Y','-1''7.431487403991564"');
SetRField(LNewObj,'Callout','ControlPoint03X','1''0.000000000000002"');
SetRField(LNewObj,'Callout','ControlPoint03Y','0"');
SetRField(LNewObj,'Callout','ControlPoint04X','9''0.046850393700751"');
SetRField(LNewObj,'Callout','ControlPoint04Y','0"');
SetRField(LNewObj,'Callout','__dbName','');
SetRField(LNewObj,'Callout','__dbUUID','');
SetRField(LNewObj,'Callout','__NoteUUID','{FFA5C43C-FC3C-40A2-AC80-C4D561E385E2}');
SetRField(LNewObj,'Callout','__NoteDescrip','This is a callout');
SetRField(LNewObj,'Callout','__KeynoteNumber','0');
SetRField(LNewObj,'Callout','__OldPlaceAs','False');
SetRField(LNewObj,'Callout','__OldBubbWidth','2"');
SetRField(LNewObj,'Callout','__OldShoulder','1''0.000000000000002"');
SetRField(LNewObj,'Callout','__OldLeaderStyle','');
SetRField(LNewObj,'Callout','__IsFlipped','False');
SetRField(LNewObj,'Callout','__isNew','False');
SetRField(LNewObj,'Callout','__version','2800');
SetRField(LNewObj,'Callout','__markerCode','1;0;15;0.125000;0.000000;2;2.000000;');
SetRField(LNewObj,'Callout','Arrow Style','');
SetRField(LNewObj,'Callout','Marker Symbol','');
SetRField(LNewObj,'Callout','Marker Scale Factor','0.039370078740157"');
SetRField(LNewObj,'Callout','MarkerAng','15');
SetRField(LNewObj,'Callout','Marker Weight','1');
SetRField(LNewObj,'Callout','__OldCtrlPt03X','304.8');
SetRField(LNewObj,'Callout','__OldCtrlPt03Y','0');
SetRField(LNewObj,'Callout','__OldCtrlPt04X','2744.39');
SetRField(LNewObj,'Callout','__OldCtrlPt04Y','0');
SetRField(LNewObj,'Callout','Keynote Legend','Default Legend');
SetRField(LNewObj,'Callout','__OldKeynoteLegend','Default Legend');
SetRField(LNewObj,'Callout','Leader Radius','0"');
SetRField(LNewObj,'Callout','OldText','This is a callout');
SetRField(LNewObj,'Callout','__IsUseReletivePath','False');
SetRField(LNewObj,'Callout','__DBReletivePath','');
SetRField(LNewObj,'Callout','Text Angle','0.00°');
SetRField(LNewObj,'Callout','Rotate Text','False');
SetRField(LNewObj,'Callout','__OldTextAngle','0.00°');
SetRField(LNewObj,'Callout','__BubbleShadowPenColor','-3');
SetRField(LNewObj,'Callout','__BubbleShadowFillColor','-3');
SetRField(LNewObj,'Callout','HorizontalTextAlignment','Center');
SetRField(LNewObj,'Callout','New Bubble Style V20','None');
SetRField(LNewObj,'Callout','New Vertical Placement','Auto');
SetRField(LNewObj,'Callout','Draw Extended Shoulder','False');
SetRField(LNewObj,'Callout','Text Style Ref','0');
SetRField(LNewObj,'Callout','Text Spacing Index','2');
SetRField(LNewObj,'Callout','Text Spacing Value','0');
SetRField(LNewObj,'Callout','Leader Angle','-150.00°');
SetRField(LNewObj,'Callout','__ObjectRotationAngle','0');
SetRField(LNewObj,'Callout','__DrawTwoSoulders','False');
SetRField(LNewObj,'Callout','__LeadingLeaderPointX','0');
SetRField(LNewObj,'Callout','__LeadingLeaderPointY','0');
SetRField(LNewObj,'Callout','__SecondaryLeaderPointX','2028.6094375');
SetRField(LNewObj,'Callout','__SecondaryLeaderPointY','0');
SetRField(LNewObj,'Callout','ControlPoint05X','5''7.866513287401574"');
SetRField(LNewObj,'Callout','ControlPoint05Y','0"');
SetRField(LNewObj,'Callout','__OldSecondaryShoulderPointX','1723.8094375');
SetRField(LNewObj,'Callout','__OldSecondaryShoulderPointY','0');
SetRField(LNewObj,'Callout','__LeaderLinesData','{
	"handles" : [
		{
			"index" : 1,
			"firstPtIndex" : 1,
			"lastPtIndex" : 4,
			"leaderType" : 0
		}
	]
}');
SetRField(LNewObj,'Callout','__CustomPointsData',Concat('{
	"handles" : [
		{
			"index" : 1,
			"type" : 1,
			"x" : 0,
','			"y" : 0,
			"bezier" : false
		},
		{
			"index" : 2,
			"typ','e" : 2,
			"x" : -1899.0359340549093758,
			"y" : -1096.40890772','73740713,
			"bezier" : false
		},
		{
			"index" : 3,
			"type"',' : 4,
			"x" : -495.96086455238139479,
			"y" : -602.84912766598','836242,
			"bezier" : true
		},
		{
			"index" : 4,
			"type" : ','5,
			"x" : -1403.0750695025280947,
			"y" : -493.55978006138570','89,
			"bezier" : true
		}
	]
}'));
SetRField(LNewObj,'Callout','Max Leader Lines','2');
SetRField(LNewObj,'Callout','__ActiveSubObject','4');
SetRField(LNewObj,'Callout','__SubObjectDataAttributes',Concat('{
	"handles" : [
		{
			"index" : 1,
			"objectType" : 1,
			"hi','ghlightingObject" : false,
			"objectPenStyle" : 1,
			"objectCl','assPenStyle" : 1,
			"objectPenPatternIndex" : 2,
			"objectPenP','atternForeColor" : 257,
			"objectPenPatternBackColor" : 256,
		','	"objectPenColor" : 257,
			"objectPenLineType" : 2,
			"objectP','enLineTypeName" : "",
			"objectThickness" : 2,
			"objectMarker','Style" : 0,
			"objectMarkernAngle" : 15,
			"objectMarkerdSize"',' : 0.125,
			"objectMarkerdWidth" : 0,
			"objectMarkernThicknes','sBasis" : 2,
			"objectMarkerdThickness" : 2,
			"objectFillOpac','ity" : 100,
			"objectOpacity" : 100,
			"fillColorByClass" : fa','lse,
			"penColorByClass" : false,
			"thicknessByClass" : false',',
			"markerByClass" : false,
			"fillOpacityByClass" : false,
	','		"opacityByClass" : false
		},
		{
			"index" : 2,
			"objectTy','pe" : 2,
			"highlightingObject" : false,
			"objectPenStyle" : ','1,
			"objectClassPenStyle" : 1,
			"objectPenPatternIndex" : 2,','
			"objectPenPatternForeColor" : 257,
			"objectPenPatternBackC','olor" : 256,
			"objectPenColor" : 257,
			"objectPenLineType" :',' 2,
			"objectPenLineTypeName" : "",
			"objectThickness" : 2,
	','		"objectMarkerStyle" : 0,
			"objectMarkernAngle" : 15,
			"obj','ectMarkerdSize" : 0.125,
			"objectMarkerdWidth" : 0,
			"object','MarkernThicknessBasis" : 2,
			"objectMarkerdThickness" : 2,
			','"objectFillOpacity" : 100,
			"objectOpacity" : 100,
			"fillCol','orByClass" : false,
			"penColorByClass" : false,
			"thicknessB','yClass" : false,
			"markerByClass" : false,
			"fillOpacityByCl','ass" : false,
			"opacityByClass" : false
		},
		{
			"index" : ','3,
			"objectType" : 3,
			"highlightingObject" : false,
			"obj','ectPenStyle" : 1,
			"objectClassPenStyle" : 1,
			"objectPenPat','ternIndex" : 2,
			"objectPenPatternForeColor" : 257,
			"object','PenPatternBackColor" : 256,
			"objectPenColor" : 257,
			"objec','tPenLineType" : 2,
			"objectPenLineTypeName" : "",
			"objectTh','ickness" : 2,
			"objectMarkerStyle" : 0,
			"objectMarkernAngle','" : 15,
			"objectMarkerdSize" : 0.125,
			"objectMarkerdWidth" ',': 0,
			"objectMarkernThicknessBasis" : 2,
			"objectMarkerdThic','kness" : 2,
			"objectFillOpacity" : 100,
			"objectOpacity" : 1','00,
			"fillColorByClass" : false,
			"penColorByClass" : false,','
			"thicknessByClass" : false,
			"markerByClass" : false,
			"','fillOpacityByClass" : false,
			"opacityByClass" : false
		},
		','{
			"index" : 4,
			"objectType" : 4,
			"highlightingObject" :',' false,
			"objectPenStyle" : 1,
			"objectClassPenStyle" : 1,
	','		"objectPenPatternIndex" : 2,
			"objectPenPatternForeColor" : ','257,
			"objectPenPatternBackColor" : 256,
			"objectPenColor" :',' 257,
			"objectPenLineType" : 2,
			"objectPenLineTypeName" : "','",
			"objectThickness" : 2,
			"objectMarkerStyle" : 0,
			"obj','ectMarkernAngle" : 15,
			"objectMarkerdSize" : 0.125,
			"objec','tMarkerdWidth" : 0,
			"objectMarkernThicknessBasis" : 2,
			"ob','jectMarkerdThickness" : 2,
			"objectFillOpacity" : 100,
			"obj','ectOpacity" : 100,
			"fillColorByClass" : false,
			"penColorBy','Class" : false,
			"thicknessByClass" : false,
			"markerByClass','" : false,
			"fillOpacityByClass" : false,
			"opacityByClass" ',': false
		}
	]
}'));
SetRField(LNewObj,'Callout','__KeynotesListUpdate','False');
SetRField(LNewObj,'Callout','TextSizePagePoints','12.000000');
SetRField(LNewObj,'Callout','Auto Fit Bubble Width','True');
SetRField(LNewObj,'Callout','Max Bubble Width','2"');
SetRField(LNewObj,'Callout','Keynote Identifier','0');
SetRField(LNewObj,'Callout','__OldKeynoteIdentifier','0');
SetRField(LNewObj,'Callout','__IsNoteUpdated','True');
SetRField(LNewObj,'Callout','__UseFirst42','True');
ResetObject(LNewObj);
			

			HMove(LNewObj,xx,yy);
			DelObject(hText);
			DelName(fakeName);
		END
	ELSE
		BEGIN
			SysBeep;
			AlrtDialog('No Text Object Selected');
		END;



END;

RUN(Test);

 

  • Like 1
Link to comment

Nope.  Unless there's something in the SDK.

 

I did it unsuccessfully for a while just using the usuall methods.  Then I tried exporting a file with nothing but a callout as a VS and got that nonsense.  

 

Turns out that nonsense is totally necessary to create a new callout from scratch if you want the leader line to work.  Without the nonsense you can create a callout, but nothing you do in the OIP after creation will create a leader line.

 

It looks like the nonsense controls the attributes.  Which I assume is why you can't do it the normal way with your menu command.

 

There's a hidden field in the Callout record called __SubObjectDataAttributes which is a big concat.  Somehow I think THAT is controlling the attributes.

Link to comment

@grant_PD For the foreseeable future, yes.

 

I think there is even more going on here than we can see.

 

Graphic elements of the callout object can be controlled from a Keynote Legend and from Text Styles.  That's in addition to callouts being attached to databases.  I think the callout object is a much more complicated object than it appears to be.

 

It wouldn't be that difficult (famous last words of everyone writing vectorscript) to make a callout replacement plug-in object that could never be a keyed note and could never attach to a database.   There may already be some out there floating around.   (I always need to check every idea I have for a script or plug-in to make sure @Sam Jones hasn't already written it.)

  • Like 1
Link to comment

Callouts really are a pain. For years I had the habit of hardly ever inserting them "fresh", instead copy-pasting from somewhere else, because it was easier than pinning down exactly what controls their attributes.

 

They also have a confusing behaviour in the way they exist in page/world units. I think you can set defaults in page units but then they convert to world units when you place them - something like that. And copying them between viewports of different scales messes them up.

  • Like 2
Link to comment

Ok, so I got this far, which indicates that Classing and Visibility in Viewports is a constant time-suck, and it would be SUPER HELPFUL to have a tool built into the UI to search and replace and destroy classes with one click or whatever.

 

The reduced-scope 2024 standard classing seems like a good logical step to less classes in general (yay), even if it means all of our symbols and classes are now out of date and duplicated, and everyone is confused as to which is the "right one" to use now.

 

Obviously I barely know what I am talking about, but my impression from 5 or so years ago is that Marionette was a way to do this (even with "callouts", etc???)

  • Like 1
Link to comment

@geo44rey I wrote a plug-in a couple of weeks ago to help consolidate classes.  It essentially remaps all objects of one class into another class with an option to delete the original class.  It's along the same lines as deleting a class and reassigning objects using that class to a different class, but the plug-in lets you do it for multiple classes at once.  The original post can be found here:

 

image.thumb.png.b210760180268492dfb0cf2e432167bd.png

 

As for Marionette, there might technically be a way to recreate my script in Marionette but I could see it being a huge pain.  Marionette is essentially a visual way of writing scripts but I find the implementation to be clunky and slow, and have several problems with the execution.  And I really don't think Marionette has a solution for the Callouts problem since it's typically much more limited than the Vectorscript / Python scripting.

Consolidate Classes.vsm

  • Like 4
Link to comment
  • 2 weeks later...
  1. VW>Preferences>User Folders>Reveal in Finder
  2. Find the Plug-ins folder.  Put the .vsm file in that folder.  (I find it very useful to make the user folder a favorites in Finder)
  3. Restart VW.
  4. Tools>Workspace>Edit Current Workspace  (or choose Workspaces… and create a new workspace based on a copy of the current one)
  5. in the Workspace Editor > Menus Tab
  6. On the left will be groups of menu commands.  Jesse's are usually in a group called JNC. Find the menu command you want
  7. On the right are a list of all the menu commands in that workspace in VW.  Open up the target menu group and
  8. Drag the new menu command on the left to the desired location on the right.
  9. Hit OK.

 

As a bonus, you could just grab the JNC heading on the left and drag it to the right.  You will now have a JNC menu.  I'm currently using 9 JNC menu commands!

 

  • Like 1
Link to comment
  • 2 months later...

I have some good news!  After doing some research, I have figured out how to handle Callouts, so the Reset Plug-in Obj Classes command posted above will now be able to force all Callouts to take attributes By Class.  Updated command is attached here and has been tested in VW2019, VW2022, VW2023, and VW2024.

 

For those playing along at home who want a little more background on how the Callout object works, the answer is surprisingly simple.  The Callout object stores the visual attribute data for each of its components in a record field called __SubObjectDataAttributes as a JSON string.  Using Python, you can parse the JSON into a Dictionary and then change the necessary key values before re-encoding back to a string and sending it back to the Callout object.  The Python script is very simple and looks something like this (when acting on a selected Callout):

 

import vs
import json

h = vs.FSActLayer()
s = vs.GetRField(h,"Callout","__SubObjectDataAttributes")

data = json.loads(s)

for k in data["handles"]:
	k["penColorByClass"] = True
	k["thicknessByClass"] = True
	k["markerByClass"] = True
	k["opacityByClass"] = True

s = json.dumps(data)

vs.SetRField(h,"Callout","__SubObjectDataAttributes",s)

vs.SetFillColorByClass(h)
vs.SetFPatByClass(h)
vs.SetLSByClass(h)
vs.SetLWByClass(h)
vs.SetMarkerByClass(h)
vs.SetOpacityByClass(h)
vs.SetPenColorByClass(h)

vs.ResetObject(h)

 

I should mention that the resulting JSON Dictionary in this case will have a single key, called "handles" whose value will be a List containing a nested Dictionary for each component of the Callout with the necessary information.  I should also mention that the implementation that Vectorworks uses for the string data contains a lot of tab characters within the data between the keys and values.  The script above will strip those tabs out, but as far as I can tell, doing so doesn't affect VW or the Callouts in any negative way and changing any attribute of an affected Callout will reset the formatting.

 

Showing the __SubObjectDataAttributes in a Worksheet, left is a Callout before running the command, right is after running the command:

image.thumb.png.0967246aa9857c5c4ab61f7f6abc5c35.png

 

I should also mention that you really have to use Python when handling the __SubObjectDataAttributes since the string length will be longer than the 2047 character cap that Vectorscript seems to have on strings.

Reset Plug-in Obj Classes.vsm

  • Like 3
Link to comment

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...