-
Posts
186 -
Joined
-
Last visited
Reputation
124 SpectacularPersonal Information
-
Occupation
Designer
-
Homepage
https://fitplot.it/vwplugins/
-
Hobbies
Vectorscript, Python, Objective C developer
-
Location
Italy
Recent Profile Visitors
4,581 profile views
-
Michael Siggers started following Paolo
-
@DomC, Yes, screen plane planar objects into groups are showing correctly. I didn't notice that I was creating objects in the layer plane and only grouped objects disappeared in the packing… So it is sufficient to change the Dup in container node like this (just the part between my comments) : #Dom @Marionette.NodeDefinition class Params(metaclass = Marionette.OrderedClass): By = 'DomC';import datetime; now = datetime.datetime.now(); y80f5 = now.year;m80f5 = now.month; d80f5 = now.day; h180f5 = now.hour; mi180f5 = now.minute; s180f5 = now.second; ms180f5 = now.microsecond; h2 = now.hour-12 if now.hour >=13 else now.hour; VersionChange1 = str(y80f5)+' '+str(m80f5)+' '+str(d80f5); VersionChange2 = str(y80f5)+'-'+str(m80f5)+'-'+str(d80f5)+'-'+str(h2)+'-'+str(mi180f5); this = Marionette.Node( "Dup in Container" ) this.SetDescription( 'Duplicates Objects in a Container or active Layer' ) object = Marionette.PortIn(vs.Handle(0), 'obj') object.SetDescription( "The input object" ) container = Marionette.PortIn(0) obj = Marionette.PortOut() obj.SetDescription( "The result object" ) def RunNode(self): l = vs.ActLayer() o = self.Params.object.value pioHandle = self.Params.container.value if pioHandle == 0: vs.Message('kein PlugIn') pioHandle = l created = vs.CreateDuplicateObject(o, pioHandle) #this part allows the groups displaying correctly if vs.GetTypeN(created) == 11: #read components in the group h = vs.FInGroup(created) while h != 0: vs.SetPlanarRef(h, 0) #set each object planar ref to top / plan h = vs.NextObj(h) #end of my added code self.Params.obj.value = created
-
Hello Dom, I use this precious piece of software to cut needed parts on a CNC machine, thank you very much! I often have to indicate, in the output, other conventional signs/geometry (for CNC extra work as blind holes for hinge housing, edging etc.). I was trying to group the rect (panel), with color lines (edges) or circles (for blind holes), whenever needed, in the part-input layer. While polylines (also with cut holes) and other geometric entities, were counted (using their BBox as rect), unfortunately, groups where not counted in the packing, they simply do not show in the final layout! I have studied the various nodes and found a solution that may be useful. The node modifies are in DrawParts -> Move and I have changed it as follows (just the commented parts): @Marionette.NodeDefinition class Params(metaclass = Marionette.OrderedClass): this = Marionette.Node( 'Move' ) this.SetDescription("This node will move an object or point by an offset in 2D or 3D. If the object is planar this node does not move it outside of its plane.") input = Marionette.PortIn( vs.Handle(0), 'in' ) input.SetDescription('An object, vector or point to move') d = Marionette.PortIn( 0, 'offset') d.SetDescription('The distance to move the object. It could be a 2D/3D vector or Point2/Point3 in the Input category') output = Marionette.PortOut('out') output.SetDescription('The result') def RunNode(self): d = self.Params.d.value i = self.Params.input.value if type(i) is tuple: if len(i) == 3: o = [0,0,0] o[0] = i[0] + d[0] o[1] = i[1] + d[1] o[2] = i[2] + d[2] else: o = [0,0] o[0] = i[0] + d[0] o[1] = i[1] + d[1] self.Params.output.value = tuple(o) else: planar = Marionette.Is2DObject(i) if not planar: if len(d) == 2: d = [d[0], d[1], 0] vs.Move3DObj(i, d[0], d[1], d[2]) else: vs.HMove(i, d[0], d[1]) #this part allows the groups displaying correctly (planar objects only) if vs.GetTypeN(i) == 11: #read components in the group and duplicate them in the default container h = vs.FInGroup(i) while h != 0: vs.CreateDuplicateObject(h, None) h = vs.NextObj(h) #end of my added code self.Params.output.value = i It seems that the duplicated object (created in the node Dup in Container) is there, but if the handle is of type Group, it does not show. In my solution, I simply cycle inside the group components and duplicate them all in the default container (the plugin object). This allows to show the group content, but I do not know where the original group is hiding… Probably there is a better solution, I am not an expert of Marionette… Paolo
-
Catenary Curve plugin for Vectorworks® just released: Catenary Curve Plugin
-
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®
-
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®
-
Module 'certifi' not found on VW2023 / Windows 10 Pro OS
Paolo replied to Paolo's topic in Python Scripting
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. -
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
-
Jeremy Best started following Paolo
-
@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.
-
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
-
- 1
-
- plugin
- perspective
-
(and 2 more)
Tagged with:
-
Mapping the elevation of a building in Vectorworks from an image
Paolo replied to Phil hunt's topic in General Discussion
As suggested by @E|FA the PlumbBob plugin should by ok for your needs: https://fitplot.it/vwplugins/PlumbBobPlugin.html There is also a standalone app (for macOS only, on the macOS app store): https://fitplot.it/plumb-bob/ -
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.
-
A new plugin object, Arches, is available from https://fitplot.it/vwplugins/opening_arches.html. 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.
-
Mouldings Plugins Version 5
Paolo replied to Paolo's topic in 3rd Party Services, Products and Events
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. -
Mouldings Plugins Version 5
Paolo replied to Paolo's topic in 3rd Party Services, Products and Events
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.