Jump to content

Running a server script in the background


Recommended Posts

Hello again, I'm getting to the point where I'm putting my VectorWorks script together. For context the idea is that I can send information over the localhost network from Vectorworks to wherever I would like. After testing the code in a VW script it does run, but its runtime overrides VW and the only way to escape is by force quitting the app. 


From a practical standpoint I don't really want the server to close with the exception of user intervention like a menu button. Is there a way to have this script running in the background as long as possible (with certain close conditions both manual and automatic) but it doesn't compromise the functionality of VW?

Attached below is the code for the server.




Link to comment

Well that scraps the first plan I had. And I'm not quite ready to take the C++ red pill yet.


Is is possible to execute a script with a button push? I believe we can make buttons in python my next idea is to execute a similar script with button pushes and keybindings. 


The idea would be every time a user saves this script runs.



Link to comment

Make it a menu item instead and edit the workspace to assign a keyboard shortcut. That will be the easiest way to make this happen in VW. That way it is available all the time.


If you make a PlugInObject you could add a button to the OIP, but you would have to select the object and then mouse to the OIP to click it. Easier to just use the menu command.

Link to comment

That solves the Sending side, but I'm having a hard time figuring out the receive. Creating the script isn't an issue, but figuring out how to run it without user intervention is since it would be annoying to need to press a button each time you want to get your data.


Can anything be done externally, where VW gets a message (localhost network) and that can be used to run a script?


If not then I'll probably need to look into the SDK

Link to comment

VW is not set up to run scripts on OPEN or CLOSE file events, but it is very doable to replace the "Open..." and "Close..." menus with custom menu scripts that run your commands after or before the respective Open(filename) or Close(filename) commands. Of course, you would have to edit the workspace on each computer you support to swap out the existing menu commands and reassign keyboard shortcuts to the new ones. But since there are multiple ways to open a file in VW – Open... command, drag and drop file on the Dock app icon, double click on a file in the Finder – you cannot add a script to each of these methods, only to the menu command. I'm not sure if this helps.



Link to comment

I am on Mac, but I'm looking to make things cross platform.


Unfortunately the SDK seems like the simplest option given the constraints. And since I have the python script flushed out I should only need to create a class and create the same functionality in C++


That being said, what are the equivalent methods for these vs:functions:

- vs.GetRField(h,"Lighting Device","Inst Type")

- vs.GetName(h)

- vs.GetClass(h)

- vs.GetLName(vs.GetLayer(h))

- vs.GetSymLoc(h),
- vs.GetSymRot(h),

- vs.Count(lightingInstrumentCriteria)

Also can I assume that the set methods are similar but need a method name change? ie VCOM::GetRField(h, "Lighting Device", "Inst Type") => VCOM::SetRField(...) I don't know if that's the correct syntax just an example


Also I've been using these scripts for referencing:






Link to comment

Assuming you’re familiar with c++ (if not, you can find decent online tutorials), getting object info is fairly easy. The VWParametricObj class will probably have all the methods you need. 

Access all the ISDK functions as members of the pointer gSDK. This includes ForEachObjectN(), which will traverse all objects and process them with a lambda. 

Communicating over the network is going to be the more difficult thing, and requires an external library. I believe the developer wiki has an example the uses libCURL

Link to comment

I'm a bit familiar I've been learning as I went this project. Using the example in the ForEachObject documentation I've gotten this far in terms of code.

Do I now need to attach this to ModuleMain?


I've attempted to follow the templates but I know that this doesn't quite work.
REGISTER_Extension<DataExchange::TraverseFunction>( GROUPID_ExtensionVSFunctions, action, pInfo, ioData, cbp, reply );


To make things clear I am looking to

1) get / set all lighting devices.  

2) place them in a list<lightingDevice>

3) Turn it into a Json String 

4) Send over the network


I can take care of 2-4 #1 is the most pressing.



class DataExchange{
	// I've changed this to be static otherwise I can't refenence it in the (gSDK->ForEachObject( allSymbolDefs, MyCallBack, & data );)
    static void MyCallBack(Handle h, CallBackPtr cbp, void *env)
       lightingDevice* pEnv = (lightingDevice*) env;


    void TraverseFunction()
        lightingDevice data;

       //I presume this fetches all defined symbols. I'm only interested in Lighting Devices is there something I can do or is there no need for concern? 
       gSDK->ForEachObject( allSymbolDefs, MyCallBack, & data );

      //Attempting to write to a file for inspection. Let me know if there is a better way
        ofstream MyFile("filename.txt");
        // Write to the file
        MyFile << data.instrument_type;
        // Close the file

// Object to format the data with.
struct lightingDevice {
    string instrument_type;
    string fixture_mode;
    string wattage;
    string position;
    string channel;
    string patch;
    string circuit_number;
    string circuit_name;


Link to comment

I would take a look at the example for UpdateSupport. That may be the best way to define the triggers for reading and writing the json file. For example, you could write to the file whenever VW becomes inactive and read whenever VW becomes active.


IStdFile is your best bet for reading and writing text files.


The SDK now includes json.hpp for parsing and creating JSON strings.


I prefer ForEachObjectN, which lets you use a standard lambda as the action function, rather than having to deal with casting env.


The action function should screen for Lighting Devices:


Using with the Lighting Device IID is much faster than using the universal name


Create a VWParametricObj instance from the lighting device handle to retrieve all your data.


You probably want a vector of lightingDevices to pass to the action function.

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.

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