Jump to content

Help with script


floring

Recommended Posts

*newbie alert*don't know python*new to Vectorworks*

 

If anyone can critique / improve this script, much obliged. 

 

The script is drawing a line. The following are the issues:

 

1. How to use PenLoc() correctly; now it is always returning 0.0, 0.0 (the center of the page)

2. How  to tell a newly created class to "Use at Creation" 

3. How to tell the plugin script editor to use spaces when tab is pressed? Strange beast this python is.

 

Finally, anything else I do wrong, anything I could do better. 

 

Thanks y'all. 

 

import vs


# Get the current cursor position
# I'd really like to use vs.PenLoc() 
cx, cy = vs.GetMouse()

# delect all items to avoid conflicts in the creation of this construction line
vs.DSelectAll()
# remember existing active class, go back to it when done with the construction line
active_class = vs.ActiveClass()



# Get the page width (it comes in inches)
current_layer = vs.ActLayer()
page_width, page_height = vs.TBB_GetPageArea(current_layer)
pw = page_width * 24.5 # translate to mm
ph = page_height * 24.5 # translate to mm

# start x,y and end x,y of the line
sx = -pw
sy = cy 
ex = pw
ey = cy 

# vs.Message("cx: {}\ncy: {}\npw: {}\nph: {}".format(cx, cy, pw, ph))
# create the line
vs.Poly(sx,sy,ex,ey)

# decorate the line, by creating a new class
def class_change_callback(obj):
    # make sure line is not left selected 
    vs.SetDSelect(obj)
    # line to be controlled by class
    vs.SetPenColorByClass(obj)
    
    class_name = "Ref Line"
    vs.NameClass(class_name) # create a new object
    
    # set color to class
    red = vs.RGBToColorIndex(65535, 0, 0) # 
    vs.SetClPenFore(class_name, red)
    vs.SetClass(obj, class_name)

    # redundant: set line weight and color to object as I don't know how to 'Use at Creation' and let class control object
    vs.SetLW(obj, 1)
    vs.SetPenFore(obj, red)
    
    # revert to originally active class
    vs.NameClass(active_class)
    
# Iterate through all objects in the document and apply the callback function
vs.ForEachObject(class_change_callback, "INSYMBOL & INOBJECT & INVIEWPORT & (VSEL=TRUE)")

 

Link to comment
  • Marionette Maven

Hi!

 

On 9/7/2023 at 10:42 PM, floring said:

1. How to use PenLoc() correctly; now it is always returning 0.0, 0.0 (the center of the page)

According to the developer wiki, you have to use GetMouse for this. There's a note stating that PenLoc will only return the location of the pen within a script, not the location of the user's coordinate of the mouse. See PenLoc

 

On 9/7/2023 at 10:42 PM, floring said:

2. How  to tell a newly created class to "Use at Creation" 

Consider using SetClUseGraphicSetClUseTextStyle, and SetClUseTexture

 

On 9/7/2023 at 10:42 PM, floring said:

3. How to tell the plugin script editor to use spaces when tab is pressed?

Can you be more clear with this? Are you saying that when you're typing code into the editor that the tab key is inserting a tab character instead of a set of space characters? Can you provide a short video demonstrating this?

Link to comment

The Vectorworks script editor is very limited and as far as I can tell, does not offer the functionality to insert spaces rather than tabs in your code. It shouldn't be a problem because the python interpreter parses either one, as long you're consistently using only tabs or consistently using only spaces. This is annoying when you're copying code from other sources, but your only alternative is to use another code editor.

Link to comment
On 9/12/2023 at 11:58 AM, Juliensv said:

The Vectorworks script editor is very limited and as far as I can tell, does not offer the functionality to insert spaces rather than tabs in your code. It shouldn't be a problem because the python interpreter parses either one, as long you're consistently using only tabs or consistently using only spaces. This is annoying when you're copying code from other sources, but your only alternative is to use another code editor.

 

Thanks! Using another editor will still result in cut and paste I guess. Is there a way to link an external editor? Not mixing tabs and spaces remains the only option.

Link to comment
On 9/12/2023 at 11:42 AM, Marissa Farrell said:

Hi!

 

According to the developer wiki, you have to use GetMouse for this. There's a note stating that PenLoc will only return the location of the pen within a script, not the location of the user's coordinate of the mouse. See PenLoc

 

Consider using SetClUseGraphicSetClUseTextStyle, and SetClUseTexture

 

Can you be more clear with this? Are you saying that when you're typing code into the editor that the tab key is inserting a tab character instead of a set of space characters? Can you provide a short video demonstrating this?

 

Thank you for the reply! Any tip is greatly appreciated.

 

GetMouse() is not accurate for my application. I think I understand what PenLoc() is meant for therefore it won't work. I scrapped this script and changed the approach. What I was looking for was reference lines to aid with creation of new items. With a shortcut. Next day I found the Guides under the Modify menu. Awesome.

 

So I tried a new script, that would take a simple line positioned with precision and direction, and assigned it to Guides class, achieving my goal precisely. ChatGPT is atrocious with Vectorworks, yet it worked well with Python. Again, any correction is welcome.

 

What is "Marionette Maven"?

 

import vs
import math
# @florin, 09/12/2023

# find the page dimensions
current_layer = vs.ActLayer()
page_width, page_height = vs.TBB_GetPageArea(current_layer)
pw = page_width * 24.5 # translate to mm
ph = page_height * 24.5 # translate to mm

# remember existing active class, go back to it when done with the construction line
active_class = vs.ActiveClass()
counter = 0 # not used
message = "" # not used

# per chatgpt, find angle between two points
# where each point has an x/y coordinates set
# these x/y coordinates are given by vw, via vs.GetSegPt1, vs.GetSegPt2
def find_angle(p1, p2):
    x1, y1 = p1
    x2, y2 = p2
    radians = math.atan2(y2 - y1, x2 - x1)
    return math.degrees(radians)

# per chatgpt, project next x/y location given angle and distance
# distance is calculated using page dimensions
def project_point(x1, y1, angle_degrees, distance):
    # Convert angle from degrees to radians
    angle_radians = math.radians(angle_degrees)
    # Calculate the new x and y coordinates
    x2 = x1 + distance * math.cos(angle_radians)
    y2 = y1 + distance * math.sin(angle_radians)

    return x2, y2

def class_change_callback(obj):
    type = vs.GetTypeN(obj)
    global counter
    global message
    #types = types + ",{}".format(type)
    counter += 1

    if type == 2: # 2 is type for line
        # get starting and ending coordinates
        cx, cy = vs.GetSegPt1(obj)
        dx, dy = vs.GetSegPt2(obj)
        
        # angles go in opposite directions
        angle1 = find_angle((cx,cy),(dx,dy))
        angle2 = find_angle((dx,dy),(cx,cy))
        
        #message = "{},{}".format(angle1,angle2)
        # start x,y and end x,y of the line
        sx, sy = project_point(cx, cy, angle1, (pw*ph)/2)
        ex, ey = project_point(dx, dy, angle2, (pw*ph)/2)

        vs.SetSegPt1(obj, sx, sy) # set next x/y in oner direction
        vs.SetSegPt2(obj, ex, ey) # set next x/y in oposite direction
        
        red = vs.RGBToColorIndex(65535, 0, 0) # red color 
        vs.SetPenFore(obj, red)	# set color of line
        vs.SetLW(obj, 1) # line weight
        vs.SetClass(obj, "Guides")
        
        vs.DoMenuTextByName("Lock",0)
        vs.SetDSelect(obj) # deselect the line
        
               
# Iterate through all objects in the document and apply the callback function
# vs.ForEachObject(class_change_callback, "INSYMBOL & INOBJECT & INVIEWPORT & (VSEL=TRUE)")
vs.ForEachObjectInLayer(class_change_callback, 3, 0, 4);	#{ Visible/Selected objects, Shallow, Editable Layers }
#vs.Message("{}".format(message))
# revert to originally active class
vs.NameClass(active_class) 
vs.SetTool(-240) # ensure Selection tool is active

 

Link to comment

The standard way to use an external editor with Vectorscript (not sure about Python), is to use {$INCLUDE FileName.Ext}.

 

Then you can edit the Included file in the external editor and only have to write the basic 3 lines of container code in the built in editor.  Or maybe you can do it all with an Include which would make the internal editor code only a single line.

 

Procedure Test;

 

{$INCLUDE Filename.ext}

 

Run(Test);

 

 

Link to comment

In Python that'll be

Import <path to file>
 

The file path starts from the plug-in folder and doesn't need the .py extension.

 

In most cases I use this script in the Vectorworks editor:

 

import <path>.main as mod

mod.main()

The <path> just points to a folder in the plugin folder.
The path folder contains 3 files:

__init__.py

main.py

code.py

 

The init file is needed to make the folder work as a Python module. It's just an empty text file names __init__.py

 

The main.py file contains:


def main():
    import <path>.code as mod
    from importlib import reload
    reload(mod)
    mod.main()

 

The code.py file contains a def called main that contains the actual code.

 

 

  • Like 1
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...