Jump to content

Paolo

Member
  • Posts

    180
  • Joined

  • Last visited

Posts posted by Paolo

  1. I have just released a plugin to create catenary curves.

     

    From Wikipedia:

    Catenary is the curve that an idealized hanging chain or cable assumes under its own weight when supported only at its ends in a uniform gravitational field.

     

     

    It is essentially a "line object" plugin: click and drag to get the initial couple of end points on the XY plane.

     

    Customizable parameters:

    • Independent Z for both ends.
    • Direction [downward (chain) or upward(arch)].
    • By length or by sag methods: you can establish the length of the chain or the chain lowest (or highest) point.
    • Buttons to extract a 3D polygon or a 2D polygon out of the PIO.

     

    More info on my site page: Catenary Curve for Vectorworks®image.jpeg.475052565f760b4e944a231bb2859658.jpegScreenshot2024-02-07alle19_26_21.png.2218015e0f77062a56325a2023589c19.png

    • Like 2
  2. ropeslogo600px.png.7c6515292007487cc00207292bcfb233.png

    This plugin creates a parametric rope out of a 3D path (NURBS).

    This object has the same behavior (for creation and editing) as the NURBS Curve tool.

    The plugin provides also a button to import / exchange the current curve with another you select on the drawing.
    More info on the Ropes Plugin site, where you can download a demo (available for Vectorworks® 2022, 2023 and 2024)

     

    To unlock the demo and get the full control on the ropes parameters, just buy a lifetime license on Gumroad®

    • Like 4
  3. I should have fixed the problem avoiding to use the 'certifi' module:

    context = ssl.create_default_context(cafile=certifi.where())

    has been replaced with:

    context = ssl.create_default_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE

    On my mac works well, I am waiting the result on the VW2023 / Windows 10 Pro OS that was giving trouble…

     

    P.S.:

    I have just received a positive response that the new code works fine also on Win 10.

    • Like 1
  4. Recently I have released a plugin through Gumroad® called Arches.

    This plugin written in Python contains a licensing algorithm that queries Gumroad through an url request.

    The Python modules required are the following:

    import certifi
    import ssl
    import json
    from urllib import request, parse, error

    and the core request is the following:

    def licenseCheck(license_key, user_email, productID):
    
    	context = ssl.create_default_context(cafile=certifi.where())
    	webConnection = testInternet()
    	
    	url_ = "https://api.gumroad.com/v2/licenses/verify"
    	pf_permalink = productID
    	params = {'product_permalink': pf_permalink, 'license_key': license_key}
    	data=parse.urlencode(params).encode('ascii')
    
    	req = request.Request(url_, data=data)
    	try:
    	  response = request.urlopen(req, context=context)
    	  get_response = json.loads(response.read())
    	except: # error.HTTPError as e: get_response = json.loads(e.read())
    		get_response ={'success': False, 'purchase': {'email': user_email, 'license_key': license_key}}
    
    	status = False
    	if get_response['success'] and get_response['purchase']['email'].lower() == user_email.lower():
    	  status = True
    	else:
    	  get_response = "Failed to verify the license."
    
    	return status, get_response , license_key, webConnection

     

    I have deeply tested it on my Mac and upon success I started to sell it.

    Nowadays I collected some customers and just one of them got the message

    ModuleNot FoundError: No module named 'certifi

    I am in contact with this user and I know he runs VW2023 / Windows 10 Pro OS.

    I have let him make some tests and the weird thing is that while receiving the module not found message, neither he is able to install it (through Marionette.VerifyOrGetLib) because certifi is already installed.

     

    I am still waiting other tests I have requested, and in the meanwhile I am asking @Vlado or @K.Lalkovski or any other expert, if the simple script:

    import certifi
    vs.Message(certifi.where())

    gives error (module not found) or, as in my case (macOS) the module path inside Vectorworks / Python:

    /Applications/Vectorworks 2023 IT/Vectorworks 2023.app/Contents/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/certifi/cacert.pem

     

    Thank you in advance

  5. On 8/18/2023 at 10:27 PM, Kevin Allen said:

    no. pity though

    @Kevin Allen, @Bruce Kieffer

    Mouldings plugins objects automatically import a symbol of the profile shape and use it for their purposes.

    When you choose the profile shape from the library browser (or from a .cpf file you have previously saved), the profile shape's symbol is imported in the drawing.

    You can edit the (local) profile symbol and all the PIOs (using that shape in the drawing) are automatically updated.

    Of course, the shape in the library is not touched at all. If you want to get back to the library shape, just delete the symbol from the drawing and choose it again from the library browser.

    • Like 4
  6. PlumbBob official site

    PlumbBob on Gumroad®

     

    Version 2.0, for Vectorworks® 2023

     

    PlumbBob is an image perspective rectification that works directly inside Vectorworks (with a plugin object and 4 command menus).

    The new version simplify the overall operations. There is no more the need to set the offsets fields, since the algorithm is now able to center the image inside the chosen key points.
    Also the image is zoomed in way to include at least the key points in the resulting image.
    It remains up to the user the option to change the final resolution of a factor of the original resolution, in order to reduce the time for the image rectification.

     

    Here below the full 2.0 changelog:

    • Autocenter: the rectified image is centered on the point where the key points diagonals crosses
    • Autozoom: the rectified image will always include (if success) the key points and as much as possible the around area
    • Resolution: the resolution factor field is there to limit the production of very large images whenever they're not needed.
    • Also an alert shows up whenever the resulting image may have a side of over 4000 pixels. This alert consent to cancel the operation, to limit to 4000px the result, or to proceed.
    • No need to say that more pixels mean more CPU effort, so, more time to create the rectified image.
    • The plugin works also when image where transformed (scale, flip or rotation)
    • Also the plugin object can be rotated or flipped
    • Objects transformations (direct and inverse) works without conversion in polygons (curves are preserved!)
    • Eligible objects are: points, lines, rects, polygons, polylines, arcs, ellipses, rounded rects and groups contents (whenever the component is eligible)
    • Object, if needed, are converted in polylines with curves composed by spline beziers that are interchangeable within 3D transformations
    • Also groups (if contents are eligible) can be transformed
    • Images transformations (direct and inverse) take into account image crop mask (if present)
    • Image crop masks are transformed as well as any other eligible 2D object
    • Like 1
  7. Hello Fabio,

    in the simplest case, with just one object 3D created in the plugin, the "core" is in the following lines:

    hTrim = vs.LNewObj() #hTrim is my 3D object I want to control the texture
    					
    from collections import namedtuple
    
    Trim = namedtuple('Trims', ['trim'])
    obj = Trim(hTrim);
    
    if not vs.CustomTexPartExists(parmHand, 1000): #parmHand is the plugin's handle
    	vs.SetTextureSet(parmHand,1)
    	vs.RemoveCustomTexParts(parmHand)
    	vs.AddCustomTexPart(parmHand, 1000, 'trim')
    	vs.SetDefaultTexMapN(parmHand, 1000, 0)
    
    vs.ApplyCustomTexPart(parmHand,obj.trim,1000);
    setTexture(obj.trim, parmHand, 1000, materialChange, classChange)

     

    The setTexture function (following) is where we set / get the OIP texture panel:

    #************************ setTexture ************************#
    def setTexture(h, hPio, idx, materialChange, classChange):
    	#classes
    	if not vs.PuseMaterials and materialChange:
    		vs.SetClass(h, vs.GetClass(hPio))
    		
    		vs.SetTextureRefN(hPio, vs.GetClTextureG(vs.GetClass(h)), idx, 0)
    		vs.SetTextureRefN(hPio, -1, idx, 0)
    
    		vs.ResetObject(hPio)
    
    	#*** material ***#
    	if vs.PuseMaterials and materialChange:
    		vs.SetClUseTexture(vs.GetClass(hPio), False)
    
    		if vs.Pmaterials == '':
    			MyList, NumItems = vs.BuildResourceList(19, 0, '')
    			if NumItems == 0:
    				MyList, NumItems = vs.BuildResourceList2(19, 345, '', True) #get it from the library
    				
    			#here I have at least the default material
    			if NumItems > 0:
    				result = vs.SetObjMaterialHandle(h, vs.GetObject(vs.GetNameFromResourceList(MyList, 1)))
    				result = vs.SetObjMaterialHandle(hPio, vs.GetObject(vs.GetNameFromResourceList(MyList, 1)))
    				vs.SetRField(hPio, vs.GetName(vs.GetParametricRecord(hPio)), 'materiale', vs.GetNameFromResourceList(MyList, 1)) #materiale is a parameter of type Material
    				vs.SetRField(hPio, vs.GetName(vs.GetParametricRecord(hPio)), 'materials', vs.GetNameFromResourceList(MyList, 1))
    		else:
    			result = vs.SetObjMaterialHandle(h, vs.GetObject(vs.Pmaterials))
    			result = vs.SetObjMaterialHandle(hPio, vs.GetObject(vs.Pmaterials))
    			vs.SetRField(hPio, vs.GetName(vs.GetParametricRecord(hPio)), 'materiale', vs.Pmaterials)
    
    		hMaterial = vs.GetObjMaterialHandle(h)
    		textureRef = vs.GetMaterialTexture(hMaterial)
    		vs.SetTextureRefN(hPio, textureRef, idx, 0)
    		vs.SetTextureRefN(h, textureRef, 3, 0)
    		
    	if vs.PuseMaterials:
    		result = vs.SetObjMaterialHandle(h, vs.GetObject(vs.Pmaterials))
    		result = vs.SetObjMaterialHandle(hPio, vs.GetObject(vs.Pmaterials))
    		
    		if vs.Pmaterials == '':
    			vs.ResetObject(hPio)
    
    	#changes in OIP rendering
    	if vs.GetTextureRefN(hPio, idx, 0, False) == -1 :
    		vs.SetTextureRefN(h, vs.GetClTextureG(vs.GetClass(h)), 3, 0)
    	else:
    		vs.SetTextureRefN(h, vs.GetTextureRefN(hPio, idx, 0, False), 3, 0)
    
    	if vs.GetTextureRefN(hPio, idx, 0, False) == 0 :
    		vs.SetTextureRefN(hPio, 0, 3, 0)
                 
    	else:
    		vs.SetTexMapInt(h, 3, 1, vs.GetTexMapIntN(hPio, idx, 0, 1));
    
    		vs.SetTexMapBoolN(h, 3, 0, 1, vs.GetTexMapBoolN(hPio, idx, 0, 1))
    		vs.SetTexMapBoolN(h, 3, 0, 2, vs.GetTexMapBoolN(hPio, idx, 0, 2))
    		vs.SetTexMapBoolN(h, 3, 0, 3, vs.GetTexMapBoolN(hPio, idx, 0, 3))
    		vs.SetTexMapBoolN(h, 3, 0, 4, vs.GetTexMapBoolN(hPio, idx, 0, 4))
    		vs.SetTexMapBoolN(h, 3, 0, 5, vs.GetTexMapBoolN(hPio, idx, 0, 5))
    		vs.SetTexMapBoolN(h, 3, 0, 6, vs.GetTexMapBoolN(hPio, idx, 0, 6))
    		vs.SetTexMapBoolN(h, 3, 0, 7, vs.GetTexMapBoolN(hPio, idx, 0, 7))
    
    		vs.SetTexMapRealN(h, 3, 0, 1,vs.GetTexMapRealN(hPio, idx, 0, 1))
    		vs.SetTexMapRealN(h, 3, 0, 2,vs.GetTexMapRealN(hPio, idx, 0, 2))
    		vs.SetTexMapRealN(h, 3, 0, 3,vs.GetTexMapRealN(hPio, idx, 0, 3))
    		vs.SetTexMapRealN(h, 3, 0, 4,vs.GetTexMapRealN(hPio, idx, 0, 4))
    		vs.SetTexMapRealN(h, 3, 0, 5,vs.GetTexMapRealN(hPio, idx, 0, 5))

     

    The variables materialChange and classChange are triggered by the user acting on some parameters in the OIP:

    # *** material change ***        
    if vs.IsNewCustomObject(parmName):
    	vs.SetObjectVariableBoolean(parmHand, 800, False)
    
    result, widgID, prmIndex, oldValue = vs.vsoStateGetParamChng(parmHand)
    if result or vs.GetObjectVariableBoolean(parmHand, 800):
    	result, outWidgetID = vs.vsoPrmName2WidgetID('', 'materials') #materials menu managed in event kObjOnWidgetPrep and in setTexture
    	if (widgID == outWidgetID):
    		materialChange = True
    
    	result, outWidgetID = vs.vsoPrmName2WidgetID('', 'useMaterials') #checkbox 
    	if (widgID == outWidgetID):
    		materialChange = True
    
    	if vs.GetObjectVariableBoolean(parmHand, 800):
    		materialChange = True
    		classChange = True
    
    	vs.SetObjectVariableBoolean(parmHand, 800, False)

     

    Of course, in the case you have more materials in one plugin (such I have in some of my Mouldings Plugins), things get more complicated.

    • Like 1
  8. A new plugin object, Arches, is available from https://fitplot.it/vwplugins/opening_arches.html.

     

    Arches-Starting-Image-small.png.26de98fd56421b99bac7de72ca666758.png

     

    It essentially creates arches openings from (so far) 33 starting models!
    Customisable on width and height as well as other parameters (as requested from the type of arch).
    Also arches openings can be decorated with stones / bricks or trims.

     

    A free demo is available for download (for VW2022 and VW2023).


    The demo is fully working (you can essay all the types!) but important parameters (width and height) are disabled.
    To get the unlimited version, you have to get the licence key (through Gumroad®).

     

    This is my first plugin that adopt a licence key mechanism (already experimented with my app FitPlot, available on the Mac App Store and at the same time through Gumroad®).


    Plugins for Vectorworks developed in Python can successfully implement the Gumroad® licence key's APIs.

    Maybe, I can start to release some of my plugins through the partener install page… @LDraminski

     

    For whom interested in the Python / Vectorworks® / Gumroad® key licensing algorithm I have adopted, please, contact me in DM.

    • Like 2
  9. The Mouldings Plugins package has been updated!

     

    ‼️[EDIT] The new version (5.2) is for Vectorworks 2022 and 2023

     

    Registered users should have received a notification e-mail from Gumroad®

     

     

    Full changelog on the site at the link below:

    https://fitplot.it/vwplugins/mouldings.html#latest

     

    Quote

     

    version 5.2:

    Release date: 2022 November, 16th

    ‼️[EDIT] Note: this update is only for Vectorworks 2022 and 2023.

    • 3D Only option. With this option the object loose the hybrid behavior.
      While loosing the 2D representation, this allows the object to be rotated in the 3D space.
      Hybrid objects can only be rotated on the screen plane, pure 3D objects can be rotated freely on the 3D space.
      Reversing an object to hybrid (unchecking the 3D Only option), will force the object to lay in the screen plane, loosing all 3D transformations. In case, a confirm dialog is showed to the user.
    • Bug fixing. Error founds have been corrected.

     

     

  10. 1 hour ago, Andy Broomell said:

     

    Everything after the first paragraph is a bit above my comprehension of how things work. 😅 But thank you for exploring this so quickly!

     

    The idea of 3D Only is very enticing but it sounds like it does open up additional complications that I'm not sure how they'd need to be dealt with.

     

     

    Perhaps related to this, I've always wondered if the "Moulding on 2D Path" tool could be made to inherently work on 3D planes (or Automatic), therefore allowing you to interactively draw wall paneling directly onto a wall, for example. And I mean the path would still be planar / not NURBS.

     

    Right now wall paneling is probably best achieved with the Frame tools, but I prefer the direct path editing available with Moulding on 2D Path tool. I'm sure generating the 2D component is what makes this idea complex, but if the tool could be set 3D Only, perhaps this opens up that possibility?

    I have edited my post before, having found a way out to the inconsistency I had found.

    I'll send you the Moulding on 2D Path plugin to you privately, so you can play with it.

     

  11. 1 hour ago, MarcelP102 said:

    Hi @Paolo

     

    I've noticed the new profiles wont show, see below. I've checked the folder, the files are there.

     

    1395199078_Profileselection.JPG.eb80d03997153e1010b98eea122c1451.JPG

     

    It's a nice update, I'm also liking the "Show Details (2D)"  option.

     

    Now that we can use the fill of the material another idea comes to mind; can this be smart like the Structural Members. So that it automatically shows the right 2D representation depending if the object is below or above the section ('hoogte snijvlak'). Using the fill of the material only when cut. And using fill of class when below section line. The dashed line representing the above section position of the profile can perhaps be another class? Or separate setting like Structural Members has.

     

    image.thumb.png.5772eeff1556924f89d7e9d1e7e13bf3.png

     

    Sorry @MarcelP102 (and other users…)

    The problem with the new profiles is due to the " char used for inches contained in the file names, that Windows does not like!

    You (and others) should receive the new corrected library via Gumroad® email.

     

    About your wish, I'll take a look as soon as I can.

  12. @Andy Broomell

    It's easy to implement a 3D Only checkbox, thus excluding any 2D object that makes the plugin "hybrid".

     

    I am making some experiment and one of the consequences of the "pure" 3D PIO is that you can rotate it in the 3D space (and not just around the Z axis of the current working plane).

     

    Once rotated in 3D, I have changed back the 3D Only checkbox to force the 2D hybrid part to be drawn, and that works, but, obviously the represented part is what the object should be in 2D plan view, distorted accordingly to the 3D rotation (see attached figure).

    1310074270_Schermata2022-07-18alle15_42_03.thumb.png.888fd024ac0f00d6638e853a634b0c73.png

    Quote

     

    A strange behaviour I noticed is that when the object rotated (X axis @ 45°, in the case below) and then changed to hybrid (3D Only set to OFF), the object matrix (entity matrix) got a reset to the planar view as soon as you try to move / copy the object. Z angle (if any) is preserved, while X and Y are zeroed.


    This does not happen when the PIO receives a reset (i.e. you change a parameter in the OIP)!

     

    This may lead to unwanted / unexpected results…

     

     

    Edit:

    I've found a way to manage this:

    when the object is rotated on X or Y axis then the 2D drawing is performed a 3D planar ref.

    The 2D is performed if 3D Only parameter is set to OFF, of course.

    Also it takes to check ON the plugin option flag "reset on rotation" to update rotation changes.

    136071533_Schermata2022-07-18alle18_03_06.thumb.png.8d2d8cac2a27b9754819deeb64060547.png

     

    That was easy for the Moulding on 2D Path, other plugins may require more effort…

     

     

     

  13. Not quite like to add chamfer (selecting edges), but drawing rectangles in 3D working plane (by hooking onto the panel itself) should be also easy.

    Then transform that rectangle(s) in Moulding on 3D path (see moulding plugins).

    Adjust the profile and other settings to your needs.

    Do the same on the other panels, or drag / copy onto other panels.

     

     

     

    • Like 1
  14. A year since the last update, here's the new version, free for old registered users.

    It includes, among many other news and improvements, the support for materials.

     

    The new version (5) is only for Vectorworks® 2022

     

    Full changelog on the site at the link below:

    https://fitplot.it/vwplugins/mouldings.html#latest

     

     

    Changelog:

    • New profiles libraries:
    1. Fypon (Fypon Mouldings Search Page)
    2. Dykes (Dykes Mouldings Browse Catalog)
    3. Updated Signorini catalog
    4. Now the full library contains than 2300 profiles!

     

    • New Plugin object named  Cannetè meaning a particular decorative technique characterized by a series of narrow repetitive half rounds / grooves / rects along a path.
    • New menu tool Canneté Calculation to compute canneté elements in the current layer, subdivided by section's size. User can give the length of the rod the elements are cut from and the program returns the number of rods needed, along with a detailed cuts list.
    • New menu tool Siding Calculation to compute sidings elements. As the above, but for sidings elements.
    • All plugins objects include material control (a check box), as well as a better management of the textures (in the texture panel of the OIP). Classes support is still available, of course.
    • Frame (Rectangular) plugin (and Frames (Array) plugin) now include the 'None' item in the frame profile popup.
    • Frame (Array): new Rail at base (extra) parameter, to increase just the rail at base. Also you can have a Frame (Array) object with styles and rails without necessarily set a frame, just set the frame profile to "None" in the profile popup (see above).
    • Improved path management for PIOs using paths, such Moulding on 2D Path and Moulding on 3D PathEasily import / exchange paths choosing from a wide variety of objects (lines, rects, arcs, polygons, polylines etc.).
    • You can also use the tools NURBS to Moulding or 2D Path to Moulding to convert many kind of objects (lines, rects, arcs, polygons, polylines etc.) respectively into Moulding on 3D path or Moulding on 2D path plugin objects. Especially for Mouldings on 3D path, you can draw / compose 2d shapes in a 3D working plane (for example a rectangle onto a door panel), then create a moulding out of it! 
    • Bug fixing. Error founds have been corrected.

     

    Mouldings_Show_V5.thumb.png.6c61474a2682926c4c659b207101640d.png

     

    • Like 1
    • Love 2
  15. I get vs.GetPt() working in an event driven plugin object (VW2022 on MacOS) with this trick:

     

    def PickPointCallback(pt):
    
          h = vs.PickObject(pt[0], pt[1])
    	
          if h != None:
                resultStatus, parmName, parmHand, parmRecordHand, wallHand = vs.GetCustomObjectInfo()
    
              if parmHand != None:
                  #do your things with the picked object
    	
          #at the end of the callback function call this
          vs.SetObjPropVS(kObjXHasCustomWidgetVisibilities, True)
        
    #plugin event loop
    theEvent, theButton = vs.vsoGetEventInfo()
    
    if theEvent == kObjOnInitXProperties:
      
    elif theEvent == kObjOnAddState:
      
    elif theEvent == kObjOnWidgetPrep:
      
    #then in the button hit event, where the get point is called…
    elif theEvent == kObjOnObjectUIButtonHit:
    	if theButton == buttonID_2:
    		#set widget visibility to false
            vs.SetObjPropVS(kObjXHasCustomWidgetVisibilities, False)
    		vs.GetPt( PickPointCallback )
    
    #finally the reset event
    elif theEvent == kResetEventID:
      
    #

     

    Without setting custom widget visibilities, calling vs.GetPt() crashes Vectorworks!

    • Like 1
  16. Objects 3D that are constructed within Vectorworks primitive tools (extrusions, extrusions along path, etc.) have full texture controls in the object render pane.

    This is not true for custom plugin objects that creates parametric 3D objects, as far as I know…

    Just the texture choice is available…

    Is there a way to show all the options?

    1351222714_Schermata2022-04-15alle11_25_43.png.31d814f1da608b00708f059f129c15f1.png

    • Like 1
  17. Mouldings Plugin are not developed with the SDK, but in VectorScript (event driven plugin objects).

     

    In Vectorscript there is no GetTextureMappingInfoN() function.


    I am still searching a way to customise the render pane, but until now, I did not found any satisfying solution.

     

    I do not know why if you create e 3D object (e.g. a simple extrusion) you get the full options on the object render pane, while if you create a 3D object through a plugin object, the object render pane is limited to the texture popup and texture choices.

     

    Somebody knows why?

     

  18. About materials, I am still figuring a way how they would live / interact  with classes. I am a little confused at this point...

     

    About the other @Andy Broomell suggestions I agree with him.

     

    Plugins objects where one class only is required (corner or mouldings on path), are easy to manage: you will be able to set attributes by class or override fills and lines with the attribute palette. The rendering (oip) tab will allow you to set texture to none, class or by one of your choice.

     

    More complex plugins (frames etc.), where more than one class is required, will take attributes of their part by their given classes (in oip classes popup for each part) unless you choose different fills or lines in   the attributes panel.

    About the texture, in the rendering tab, choosing none will use the solid color fills in rendering as above said. Using by class, will use each class texture (whenever set), otherwise choosing a texture from the list, will cause that texture to be applied to the whole parts of the object.

     

    I am at a good point with these changes, hope to test and finish up them in a short time.

    • Like 2
    • Love 1
×
×
  • Create New...