Jump to content
Developer Wiki and Function Reference Links ×

Add Tool to Workspace


DomC

Recommended Posts

Hello

So far it works implementing a Tool in the Workspace and Creating a new Palette Group. So far it works for path Objects or Point Objects (vso). Event Enabled or not Event Enablet. But I can't get it to work with a VST. I tested with this tool "Blindfront" This one here:


As soon as I manually drag it into the workspace the tool works. and also after that the tool i added with the script works. So far the workspace itself looks identical if i drag manually the tool in the workspace as if i create the tool by script. I think I am missing some important parameter here.
The Tools is placed into the palette and is shown ad expected but not the tool can't be selected. 

Anybody can help?

Here My small test:
 

#Get Group Palette by Index 1 (0 is Construction palette)
pName = vs.ws2GetToolAt("", 1)
result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID = vs.ws2GetToolInfo(pName)

vs.AlrtDialog('Put Tool in ' + outDisplayName)

#The .vst is already in the Plug-Ins Folder

# id of group palette
tsPath = pName #outDisplayName#GetPalettePath('Werkzeuggruppen')

tsName = 'NewPalette'
tsNameUniversal = tsName #can be a uuid or just here for Testing 'NewPalette'
vs.ws2CreateToolSet(tsPath, tsNameUniversal, tsName, '')
path_new_tool = '/'.join([tsPath, tsNameUniversal])

# Add tools
ok = vs.ws2CreateTool(path_new_tool, "Blindfold", 3) #Don't know what this index 3 is used for

#vs.ws2GetToolInfo(toolPath)
vs.ws2CommitChanges(False, False)
bWorked = vs.wsEditEnd(False)
    

 

Edited by DomC
Link to comment
  • 2 years later...

@DomC @JBenghiat I am trying to get my head around using vs.ws2CreateToolSet. Ideally I would like to use it in an install.py script to add a Toolset and Tool to a users currently existing workspace.
 

What would be considered the tool path in this function? I presume it is not the file  location in the plugins folder? 

 

the tool I want to add is in the plugins folder and I can add it manually in the workspace editor. But I am really wandering how I get a handle to this tool to add it to the current workspace. 
 

 

 

Link to comment

@Sebastiaan the "path" defines the location of the tool in the workspace, so something like palette\toolset\. A menu path would be something like Tools\MySubmenu\MyOtherSubmenu.

 

I needed to do a fair amount of extending the built-in workspace functions in order to install tools in menus in specific places. You also need to provide the user with an option if your target toolset does not exist in the user's current workspace.

Link to comment
Just now, JBenghiat said:

@Sebastiaan the "path" defines the location of the tool in the workspace, so something like palette\toolset\. A menu path would be something like Tools\MySubmenu\MyOtherSubmenu.

 

I needed to do a fair amount of extending the built-in workspace functions in order to install tools in menus in specific places. You also need to provide the user with an option if your target toolset does not exist in the user's current workspace.


what I would want to do is create a new toolset, if it does not yet exist. And then place the tool that was just placed in the plugins folder, by install.py in that new toolset. 
 

but I now read this as if the tool already needs to be in the workspace before you can place it in the new toolset? 
 

would it be possible at all with the built in workspace tools to create a new toolset and place newly installed plug in in it in one go? 
 

I could of course add instructions and let the user edit the workspace manually but I was able to automate everything else and this would make the user.  experience complete 

Link to comment
17 hours ago, JBenghiat said:

The path is the container where you WANT the tool to reside in the workspace, like specifying a directory path for a file. 
 

Yes, you can create new pallets and tool sets 

 

I am really struggling with this if I run @DomC example script it crashes and also if I run below script with my own names is crashes when it tries to execute vs.ws2CreateToolSet. 

 

In this example I used tsPath = pName (ike in DomC's example) for the tool path and then it crashes. If I use tsPath = outDisplayName then it does not crash but nothing happens. It crashes in 2024 too. 

 

The tool I am trying to add is a plug in object .vso


Code that crashes:
 

pName = vs.ws2GetToolAt("", 1)
result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID = vs.ws2GetToolInfo(pName)

msg = "result = {}\routDisplayName = {}\routShortcutKey = {}\routShortcutKeyModifier = {}\routResourceID = {}".format(
    result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID)
vs.AlrtDialog(msg)

tsPath = pName

toolset_path = "/".join([tsPath, "STB Tools"])

vs.ws2CreateToolSet(tsPath, "STB Tools", "STB Tools", "")

vs.ws2CreateTool(toolset_path, "FenceChainPy", 3)

vs.ws2CommitChanges(False, False)

 

Code that does not crash, but does not update the workspace:

pName = vs.ws2GetToolAt("", 1)

result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID = vs.ws2GetToolInfo(pName)
msg = "result = {}\routDisplayName = {}\routShortcutKey = {}\routShortcutKeyModifier = {}\routResourceID = {}".format(
    result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID)
vs.AlrtDialog(msg)

tsPath = outDisplayName 

toolset_path = "/".join([tsPath, "STB Tools"])

vs.ws2CreateToolSet(tsPath, "STB Tools", "STB Tools", "")

vs.ws2CreateTool(toolset_path, "FenceChainPy", 3)

vs.ws2CommitChanges(False, False)

 

Link to comment

Hi
Not in that matter right now. Minimum i can confirm it crashes 😁
missing icon path or missing wsEditBegin or wsEditEnd. The above Test worked in 2022 and 2023. Maybe there was changed something in the meantime.

Edited by DomC
Link to comment
36 minutes ago, DomC said:

Hi
Not in that matter right now. Minimum i can confirm it crashes 😁
missing icon path or missing wsEditBegin or wsEditEnd. The above Test worked in 2022 and 2023. Maybe there was changed something in the meantime.


just my luck. I guess I should report this then….

Link to comment

Maybe I should just give up on this. Since creating a tool set fails over and over I tried creating a tool palette in stead. I can create a tool pallette with ws2CreateToolPalette but I can not place a tool inside it with vs.ws2CreateTool. I use vs.ws2GetToolAt to return the tool path but using that does not create the tool. 

In the documentation I read that vs.wsEditBeginN and vs.wsEditEnd require a 'company name'. Do these tools only work if you are a registered developer? I tried to enter the category name in there too but that fails. 

I tried to add a tool to the basic tool pallette and that fails too. This script below does not put the tool in the basic tool palette and I can not figure out why. Would anyone have a simple stand alone test script that adds items to the workspace?

 

import vs

# Start editing workspace
vs.wsEditBeginN("View", "")

# Get Basic palette path (index 0)
palettePath = vs.ws2GetToolAt("", 0)
vs.AlrtDialog(f"Basic palette path: {palettePath}")

# Add tool to Basic palette
ok = vs.ws2CreateTool(palettePath, "Blindfold", 2)
vs.AlrtDialog(f"Tool add success: {ok}")

# Save and end session
vs.ws2CommitChanges(False, True)
vs.wsEditEnd("View")

vs.AlrtDialog("Done.")

 

Link to comment
45 minutes ago, JBenghiat said:

Don’t mix the ws2 commands with the other ws commands. The latter are for adding to a palette and menu labeled “Third Party”

 

you’re trying to add the tool from the example at the top of the thread, and not

vs.ws2CreateTool(toolset_path, "FenceChainPy", 3)

 

I have tried both tools actually I also placed the Blindfold tool from the TS OP in my plugins folder as well. The tools are both loaded as I can see them and manually place them via the workspace editor. 

I now excluded the ws start and end functions and still no tool is placed in the basic tool palette.

See three attempts below which all do not place a tool in the basic tool palette and also a screenshot of the result of:
palettePath = vs.ws2GetToolAt("", 0)
vs.AlrtDialog(f"Basic palette path: {palettePath}")
 

import vs

# Get Basic palette path (index 0)
palettePath = vs.ws2GetToolAt("", 0)
vs.AlrtDialog(f"Basic palette path: {palettePath}")

# Add tool to Basic palette
ok = vs.ws2CreateTool(palettePath, "FenceChainPy", 3)
vs.AlrtDialog(f"Tool add success: {ok}")

# Save and end session
vs.ws2CommitChanges(False, True)


vs.AlrtDialog("Done.")
import vs

# Get Basic palette path (index 0)
palettePath = vs.ws2GetToolAt("", 0)
vs.AlrtDialog(f"Basic palette path: {palettePath}")

# Add tool to Basic palette
ok = vs.ws2CreateTool(palettePath, "Blindfold", 2)
vs.AlrtDialog(f"Tool add success: {ok}")

# Save and end session
vs.ws2CommitChanges(False, True)


vs.AlrtDialog("Done.")
import vs

# Get Basic palette path (index 0)
palettePath = vs.ws2GetToolAt("", 0)
vs.AlrtDialog(f"Basic palette path: {palettePath}")

# Add tool to Basic palette
ok = vs.ws2CreateTool('Basic', 'Blindfold', 2)
vs.AlrtDialog(f"Tool add success: {ok}")

# Save and end session
vs.ws2CommitChanges(False, True)


vs.AlrtDialog('Done.')

 

Screenshot 2025-06-04 at 13.31.59.png

Edited by Sebastiaan
Link to comment
27 minutes ago, JBenghiat said:

@Sebastiaan you’re assuming the basic tool palette is at index 0. It may not be—hence my module that searches for a named palette. 


No I am not assuming that, I tested it and it does point to the basic tool palette, yes in the production script I will add a name check, but at this point I am unable to get this simple test script do anything. I really appreciate you helping out and sharing your code, which is very sophisticated. . But I am trying to get my first simple test script to run so I can build on top of that and I really have no clue at this moment what I am doing wrong. 

See below proof that the index 0 points to the basic tool palette in the workspace that I am testing in:

 

import vs

# Get Basic palette path (index 0)
palettePath = vs.ws2GetToolAt("", 0)

# Retrieve and show display name
_, displayName, _, _, _ = vs.ws2GetToolInfo(palettePath)
vs.AlrtDialog(f"Display name of palette at index 0: {displayName}")

returns:
Screenshot2025-06-04at15_37_30.png.27667171439c213202ae082ffe78a3be.png



 

Link to comment

Hi 

I think, it crashes because of the icon_path parameter the following work here. Creating Tools Set in Tools and then add a Tool

 

import vs

# Start editing workspace
vs.wsEditBegin("View")

# Get Basic palette path (index 0)
pName = vs.ws2GetToolAt("", 1)
vs.AlrtDialog(f"Basic palette name: {pName}")
result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID = vs.ws2GetToolInfo(pName)
vs.AlrtDialog(str([result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID, pName]))

tsPath = pName
universalName = 'universal_name_f01b8'
setName = 'NewSet'

vs.AlrtDialog(str([tsPath, universalName, setName]))

icon_path = os.path.join(vs.GetFolderPath(1), 'Vectorworks 2025.app', 'Contents', 'mock-texture-overall.png')


ok = vs.ws2CreateToolSet(tsPath, universalName, setName, icon_path)

vs.AlrtDialog(f"Tool add success: {ok}")

toolPath = f"{tsPath}/{universalName}"
vs.AlrtDialog(f"tool Path: {toolPath}")
# Add tool to Basic palette
ok = vs.ws2CreateTool(toolPath, "Blindfold", 2)
vs.AlrtDialog(f"Tool add success: {ok}")

vs.wsEditEnd(False)
# Save and end session
vs.ws2CommitChanges(False, True)


Edit:
It seems, that if ToolSet is not exists it needs an icon path even the icon was not found empty string let it crash. Also None crash.
It seems to work with False, aString as the icon_path but not with None or empty string.

Edited by DomC
  • Love 1
Link to comment
5 minutes ago, DomC said:

Hi 

I think, it crashes because of the icon_path parameter the following work here. Creating Tools Set in Tools and then add a Tool

 

import vs

# Start editing workspace
vs.wsEditBegin("View")

# Get Basic palette path (index 0)
pName = vs.ws2GetToolAt("", 1)
vs.AlrtDialog(f"Basic palette name: {pName}")
result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID = vs.ws2GetToolInfo(pName)
vs.AlrtDialog(str([result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID, pName]))

tsPath = pName
universalName = 'universal_name_f01b8'
setName = 'NewSet'

vs.AlrtDialog(str([tsPath, universalName, setName]))

icon_path = os.path.join(vs.GetFolderPath(1), 'Vectorworks 2025.app', 'Contents', 'mock-texture-overall.png')


ok = vs.ws2CreateToolSet(tsPath, universalName, setName, icon_path)

vs.AlrtDialog(f"Tool add success: {ok}")

toolPath = f"{tsPath}/{universalName}"
vs.AlrtDialog(f"tool Path: {toolPath}")
# Add tool to Basic palette
ok = vs.ws2CreateTool(toolPath, "Blindfold", 2)
vs.AlrtDialog(f"Tool add success: {ok}")

vs.wsEditEnd(False)
# Save and end session
vs.ws2CommitChanges(False, True)



 

Thank you so much!! that works!!

I tested and it appears that vs.wsEditBegin and vs.wsEditEnd are indeed not necesairy.

Now I am still curious why putting a tool directly in a tool pallette or the basic tool palette did not work for me and I will keep trying. But thank you so much again, I will continue building on this!!

Link to comment

@Sebastiaan The Basic palette actually has a single tool set called "View/Draw". You can see this in the Workspace editor or if you open the workspace file with a text editor. So you would add the tool to the first palette of the first toolset. All palettes contain only tool sets, and tool sets contain only tools.

 

I realized my example on Github was misleading -- the demo script installs your tool next to an existing tool.

 

A script to add to the basic palette using my library would look something like:

import workspace_edit as we

tsPath = we.GetToolsetPath("Basic", "View/Draw")

if tsPath != '':
      vs.ws2CreateTool(addPath, "Blindfold", we.kVectorScriptTool)
      restart = False
      reload = True
      vs.ws2CommitChanges(restart, reload)

 

Link to comment
1 hour ago, JBenghiat said:

@Sebastiaan The Basic palette actually has a single tool set called "View/Draw". You can see this in the Workspace editor or if you open the workspace file with a text editor. So you would add the tool to the first palette of the first toolset. All palettes contain only tool sets, and tool sets contain only tools.

 

I realized my example on Github was misleading -- the demo script installs your tool next to an existing tool.

 

A script to add to the basic palette using my library would look something like:

import workspace_edit as we

tsPath = we.GetToolsetPath("Basic", "View/Draw")

if tsPath != '':
      vs.ws2CreateTool(addPath, "Blindfold", we.kVectorScriptTool)
      restart = False
      reload = True
      vs.ws2CommitChanges(restart, reload)

 


thank you that makes so much sense. Of course I have seen the view/draw toolset whenever I edited a workspace but did not make the link with this. 
 

That explains the Create toolpalette issue too. I would have to create a toolset within the toolpallette too. 
 

also I came to the conclusion that perhaps one can not check if a plugin itself already exists within a toolset? 

Link to comment
9 minutes ago, Sebastiaan said:

also I came to the conclusion that perhaps one can not check if a plugin itself already exists within a toolset? 

 

If you know the tool set name, then `we.GetToolsetPath('Tool Sets', 'ExistingPlugin') != 0` would be true if the tool exists. If you want to check the entire workspace, you would have to combine the palette iterator and the tool set iterator to look for the tool in every tool set.

  • Like 1
Link to comment
39 minutes ago, JBenghiat said:

 

If you know the tool set name, then `we.GetToolsetPath('Tool Sets', 'ExistingPlugin') != 0` would be true if the tool exists. If you want to check the entire workspace, you would have to combine the palette iterator and the tool set iterator to look for the tool in every tool set.

Thank you so much @JBenghiat and also @DomC  your replies have made me understand these functions now a little bit and I think this topic now compensates the minimal documentation of the workspace functions. I am happy now! 

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...