Jump to content

DomC

Member
  • Posts

    604
  • Joined

  • Last visited

Everything posted by DomC

  1. Hi You can use the "Get Item" to get an element of a list. Input 0 to get first Item. So 10th Item you get with input 9.
  2. This looks like, the symbol was edited last while the design-layer had another layer scale thank the layer scale of the actual active layer. Normally it helps co activate all, cut (cmd/ctrl. + X) and paste (cmd/ctrl + V). In this case it seems, the code attached to the add-node is broken. I can correct it as follows: 1. cut and paste 2. Double click and edit "less equal" and "greater equal" 3. Then the wires to the add node desapears and I reconnect again then it works. I think there is still an issue which can corrupt Marionette scripts. If you insert a red symbol on a design-layer which have a different layer scale than the layer scale was active while the symbol was created.
  3. As the concat node is, it converts the input to a string and then loop the character and adds them. #inputs stringIn = str(self.Params.stringIn.value) #script newString = '' for s in stringIn: newString = newString + s #outputs self.Params.stringOut.value = newString I am not sure but I would expect from this node, it should do something like this: #inputs stringIn = self.Params.stringIn.value #script newString = '' for s in stringIn: newString = newString + str(s) #outputs self.Params.stringOut.value = newString
  4. Hi You want to attach a Text property on a Marionette Object and then inside the Script ask for the Text Properties attached to the Marionette PIO? I think if a Marionette Object can get some infos from the text menu, it would be possible. You can handle the Parent PIO, but I do not see, that a Marionette can get some text Infos by the text menu. You could get the class of the Parent PIO and the Text Style of the Class as a workaround maybe. But directly the Text Style I think works not with a Marionette Object Node. Here An example, if you get the text style of the parent PIO class. Side Note: First Time I use concat node, it seems to convert the input list to a string instead of concat the input strings, which is somehow not what I would expect. It converts the List in a string first ... TextStyleByPIO_class.vwx
  5. Depending of the Skills and what the End-Result should be. Even a Script with less parametric (width, depth, height) but with a lot of Graphical Details (rounded edges different materials, Fittings etc.) will give you a lot of Nodes by create every object by script. So when you start your script is pretty compact. At the end you want to add record formats, different surfaces, textures, colors, switching on of objects, replace handles etc. etc. So it can be your script if you start looks very different from what you really use at the End. I think we could group some of different strategies. I show you here 4 different approaches for writing a Script with Marionette: 1. Geometric Strategy. Like you would draw it manually maybe. While in Marionette this means if you need a middle Point you have to draw an object or if you need a parallel contour you have to create it. Also geometrical could be we had a Node that calculates as example a parallel shape but do not draw an object. Here an example which do the job of ground-plate and foots Example: Here are Rectangle is created and then a parallel contour to this rectangle the edge points of the contour are taken for the foot Objects. The Advantages of this would be, if you have a non rectangular shape it would still do the job. 2. Calculation Strategy with native-Node-Math-Calculation. This Means you would calculate the points first and then create the Objects at the resulting pre-calculated points. With "native-Node-Calculation" I mean, that every simple math calculation is created by nodes. This generally results in a lot of nodes but everything is directly visible. So for small stuff this is OK. 3. Hybrid technique by using function Nodes: The technique from my example 2 can topple the Advantages of graphical Scripting to code-Scripting. Because a simple math like (a+b-c*2-25+1-2+a*4+a-5+a/2) is fast written by keyboard and need very much time to scripting node by node. Function Nodes can help a lot to optimize Marionette Workflows. While Standard-node-Library have one function node, I often use function2 or function4 (4 input). Look next, that example which does the same as Example 2 but without the math and Point nodes. The More calculations you need the more time you save with that workflow. I wrote the formula over the Node. It need the same reflections (not really more brain) like example 2 but is more compact. The only special here is, that I create the points with the brackets instead with the nodes. 4. Using existing Geometry. If you have a simple parametric (width, depth, height as Example) and a high grade of Details of your geometry the workflow of scripting every object is getting not the best Option. There are Custom Nodes, which allows to handle existing Geometry instead of creating Geometry. Here an Example, which takes "prototype" Geometry of your Object and "reshape it" in x, y, and z direction. The big advantages is, that graphical Details you draw in your Object will not blow ob your network and also you can input different but similar types of your object (one with frame, one with plate backside, one with rectangular foots etc. etc.) without doing a new script. Just a short picture of example #4. I just made some holes and profiles to the case. But the script is the same, no matter if more details are added. On the negative side, just half of the nodes are content of the standard-Library (It is not on me to change that). If I have to create a quite simple parametric (like a showcase). I combine Strategy 3 and 4 for myself. So one part like the hull is maybe just x y z parametric. The other part are maybe panels and data or part list informations I script additionally. You can also combine something like in Strategy Example 4 with several x y z reshape operations and two different symbols. I think maybe too much informations for a beginner but that example is pretty perfect to study the different scripting workflow. At the end it is matter of taste and what I like most on Vectorworks we have always the freedom to have our own taste. I also learn always something new, If I see scripts from others. Even from beginners maybe think of something new which also old rabbits can absorb in their workflows. Plint Example.vwx
  6. Hello Welcome to the Marionette Forum. I think your script looks quite good. My workflow is often to first calculate all necessary points and data. After That I create the Objects. Also I use a lot of custom nodes to save number of nodes (Enhanced Rectangle, Function 2, BBox Enhanced) but this is not necessary per se. Creating Rectangle to find the corner point is something I would not do generally. Also Mirroring is not necessary, if your feeds are circles or squares. To Mirror correctly you need one horizontal and one vertical axis. In your Script there is only one Axis. Also you need to mirror one Feed over a Diagonal Axis and if the shape is not a square, this had to be calculated. Or you Mirror at the Vertical Axis, then you mirror the resulting object along the horizontal axis. The Get Item in the Screenshot, gets the first second duplicate (top left) and mirror again along the vertical axis. By the way, mirroring should work like this: Mirror Example.vwx
  7. Hi Nice Example. You should use the 3D Poly. Ohne Titel 1.vwx
  8. tkinter could be installed with the Marionette python Modul importer. But at the Moment this maybe also not work out of the box. And by using tkinter I had negative effects resp. some functions maybe additional code to make it run in an embedded python. Maybe off-topic. For Crossplatform Clipboard, this script could be used: import math import os import subprocess major, minor, maintenance, platform = vs.GetVersion() text = 'Hello World' def addToClipBoardWin(text): command = 'echo ' + text.strip() + ' | clip' os.system(command) def addToClipBoardMac(text): process = subprocess.Popen('pbcopy', env={'LANG': 'en_US.UTF-8'}, stdin=subprocess.PIPE) process.communicate(text.encode('utf-8')) if platform == 1: addToClipBoardMac(str(text)) else: addToClipBoardWin(str(text))
  9. That little test works here. It seems the nested callback of the wiki-example is a little bit too ambitious. vs.DSelectAll() def resultCallback1(): h1 = vs.FSActLayer() vs.DSelectAll() p1 = vs.GetSegPt1(h1) p2 = vs.GetSegPt2(h1) vs.Locus(p1) vs.Locus(p2) vs.CallTool(-201, resultCallback1)
  10. Hi I just stumpled over that here: https://developer.vectorworks.net/index.php/VS:CallTool It seems, that CallTool is able to server a callback function. It is satisfying great to see every step of better python interaction with Vectorworks. Unfortunately it seems, that the example code on the developer Wiki does not work here. Anybody tried something already which is using that callback feature?
  11. Hello I think the issue with the script that makes it slow is, that you loop the light devices and in that loop you give a search-request with ForEachObject. If you have many objects in your drawing a search-request over all objects in the Drawing could take maybe one second and if you have that 250 times in a loop it will take 250 seconds as example. The better way in my opinion 1. Use ForEachObject just once on all Objects that could be your target light objects () 2. Then loop all light devices from data (as you do) 3. Then do it as following: if (isAvailable): lights = [] #name, handle def get_lights(h): n = vs.GetName(h) lights.append([n,h]) c = "((PON='Lighting Device'))" vs.ForEachObject(get_lights, c) for p in data['LightingDevices']: uid = p['__UID'] for light_name, h in lights: #loop through the found light objects in the drawing if light_name == uid: instrType = p['instrumentType'] instrMode = p['fixtureMode'] wattage = p['wattage'] weight = p['weight'] position = p['position'] purpose = p['purpose'] channel = p['channel'] unitNumber = p['unitNumber'] universeAdress = p['patch'] circuitNumber = p['circuitNumber'] circuitName = p['circuitName'] dmxLine = p['dmxLine'] dmxFootprint = p['dmxFootprint'] deviceType = p['deviceType'] color = p['color'] template1 = p['template1'] template2 = p['template2'] user1 = p['userField1'] user2 = p['userField2'] user3 = p['userField3'] user4 = p['userField4'] user5 = p['userField5'] user6 = p['userField6'] className = p["class"] eachLight(h) The loop in loop will be very fast. Much faster then the search-request (ForEach ...) inside a loop. Untested code but I bet a beer this would do the job faster
  12. Hi It should be possible, to use the "Attributes"-Node to set fill pattern to 0. Connect it after your object and set it to Empty Fill. After That attach your colors. The Problem could be that the "Attributes" node replace also the line weight and line style. If that is a problem you can use the "function"-Node. And just paste vs.SetFPat(x, 0) in the input field.
  13. Hi I think this object is between 2-40 hours to create. So I post without taking the order. It depends on which level of Detail you really need (Material Thickness , drillings for screws etc.) I can give you or somebody else a start-assist and a possible workflow. A sketch, what pitch, height, span, base size exactly means were nice because it is a big part of the work to specificate exactly which values should be variable. It is about the work of 3 hours (but always the first 60% from something are done very fast. It would be enough if you do not need any screws and if the material thickness on all edges would be the same and if you need just the hull of the material not the single parts and how they exactly cutted in raw form (miter etc)). Once more I ask myself, how it is possible to create exact Elements by using the non-metric-unit-system (just a gloss a place whenever I have the chance :-) BENT_v1.vwx
  14. Hi Marionette has his own function to deside (and with that if it should use a 3D Move, 3D Rotate or 2D Move, 2D Rotate etc.) if an object is planar or not. This concept has some limitations. If you edit the code to this, the rotate node will work inside the PIO. Double click the node and delete the first line, then you can edit the code. #planar = Marionette.Is2DObject(obj) cx = center[0] - offset[0] cy = center[1] - offset[1] cz = center[2] - offset[2] #if planar: vs.HRotate(obj, (cx, cy), r[2]) #else: # vs.Set3DRot(obj, r[0], r[1], r[2], cx, cy, cz) In this case, the Rotate-Node deside, that it wants to use the vs.Set3DRot() command to the symbol. which seems to work, if the symbols are on the layer. Inside the PIO it does not work. But this will not work, if the symbols are on screen plan. Inside the PIO the symbols are placed on a screen-plane like place (top plan view). I think it is related to the different plane- and container-concepts that makes it very frittered and hard for one node to handle.
  15. Hi Have you tried update on SP2 or SP3? Even if the "Data Mapper" runs without any data and connection it should show an error message.
  16. Hello Does it maybe work if you do something like this: try: vs.SetRField(h2,'Massing Model','2Ddisplay','Roof') #your code except: pass #or do someting like taggging the object as "too complexe" or do another function Alternatively you can put something heavy on your enter key, while script is running.
  17. Version 1.0.0

    75 downloads

    This Script it made for users which have an Vectorworks Architecture but have not the core business to draw walls, slabs and roofs to make a presentation ambient for their designs. It helps to create room situations very fast and especially very easy. 1. Concept It pulls Symbols out of a Symbol folder which are Room-Presets. As Presets Rooms can exist, that have a rectangular shape and inner dimension of exact 2 meters. Slabs are supported also (No extrudes etc.) and roofs. Best Practice maybe is to keep existing presets and just change classes as example. If we are working with presets we can "save" a lot of parameters in the Object-Info-Palette which makes it faster and easier to use. 2. Workflow Copy Symbolfolder and PlugIn in your project and you can use it immediately. If you want to change details you can ungroup (cmd/ctrl. U) the objects into Walls and slabs. So you are able to insert Windows, Doors or changing other Details. 3. Known Limitations/Details - Rectangular Room presets only - Switch on/off ceiling with classes - Texturize by classes - Changing classes by editing preset Symbols and attach other classes/attributes - You can Mirror the Room to get left/right rooms
  18. Hello Chris solved his situation with putting the top/plan component on screen-plane and use set parent to move it into the symbol. In the meantime I made an node for SetPlanar Ref. The includes Command (vs.Set2DComponentGroup) needs a group of screen-plane objects to work. So use the Set Planar Boolean and the group node for your geometry. For a hybrid symbol with 3D and top/plan the SetComponentGroup is not necessary. SetComponentGroup would need to set front, left, section views etc. Script Set2DComponentGroup.vwx
  19. Hello Same Issue here. It seems as soon as we have light from a HDRI this light is intensified by exporting a Panorama. I think most of users just exports the panorama without choosing the same Render-Style as the use in Vectorworks. Then the Result is Standard-RenderWorks with maybe no HDRI light attached and looks not too bright.
  20. Just read the initial post. "Workgroup folder" OK, now it is getting interesting. It depends on platform you work and workgroup folder is stored in the system I think (plist or registry). But I would not use this it is digging deep and it may not work anymore with newer versions etc. maybe hard to get it to work again. Also I did not checked if this is still working. #Windows import getpass import shutil HSFPath = vs.GetFPathName() vs.AlrtDialog(HSFPath) #Application 1 #User App Data 12 target = 'Users/dominiquecorpataux/Desktop' from winreg import * aReg = ConnectRegistry(None,HKEY_CURRENT_USER) aKey = OpenKey(aReg, r"Software\Nemetschek\Vectorworks 24\General") WGF_Path = QueryValueEx(aKey, "Workgroup Folder 0") #vs.Message(WGF_Path[0]) target = WGF_Path[0] vs.AlrtDialog(str(target)) #on mac import plistlib #MacFile = 'Users/dominiquecorpataux/Library/Preferences/net.nemetschek.vectorworks.2019.plist' pl = {} with open(file, 'rb') as fp: pl = plistlib.load(fp) vs.AlrtDialog(str(pl.get("NNA Workgroup Folders"))) vs.AlrtDialog(pl["NNA Workgroup Folders"])
  21. It should work with something like this: (Not tested but should work) import os res_file = "Path/to/your/file.vwx" if os.path.isfile(res_file) == False: vs.AlrtDialog('Path error') else: listID, symDefNum = vs.BuildResourceListN( 16, res_file ) for index in range(1, symDefNum+1): vs.ImportResourceToCurrentFile(listID, index) To grab several res files in a folder and his sub-folders: import unicodedata import os def get_res_files(folder): file_list = [] for path, subdirs, files in os.walk(folder): path = unicodedata.normalize('NFC', path) ## Valid values for form are ‘NFC’, ‘NFKC’, ‘NFD’, and ‘NFKD’. for name in files: filename, file_extension = os.path.splitext(name) if file_extension == '.vwx': fullpath = os.path.join(path, name) fullpath_string = unicodedata.normalize('NFC', fullpath) file_list.append(fullpath_string) return file_list Then you could loop through several res files: res_file_list = get_res_files('Folder/to/Libraries') for res_file in res_file_list: listID, symDefNum = vs.BuildResourceListN( 16, res_file ) for index in range(1, symDefNum+1): vs.ImportResourceToCurrentFile(listID, index) If you have issues with the path, maybe try: from pathlib import Path home = str(Path.home()) filepath = home+'/google/yourpath/yourfile.vwx' #to be cross-platform always use something like this: filepath = os.path.join(folder,folder,folder,file)
  22. The Function I use CreateChainDimension: def create_chain_dim_vertical(intersection_points_sorted, x, offset, vp_scale): #standardly im text is left if there is no place between threshold_2_dimension, dimoff1, dimoff2, dimoff3 = create_globals(vp_scale , layer_scale , units) start = intersection_points_sorted[0] h1 = None; h_first = None prior_segment_length = 0 prior_shifted_leftright = False; prior_shifted_up = False for i in range(len(intersection_points_sorted)-1): # startPt is always last endPt end = intersection_points_sorted[i + 1] segment_length = abs(end - start) if segment_length > epsilon: vs.LinearDim((x,start), (x,end), offset, 4, 769, True, 0.1) if data['b_debug_dim_color']: vs.SetPenFore(vs.LNewObj(), (65000,0,65000)); color = (65000,0,65000) if i > 0: h2 = vs.LNewObj() if not vs.GetObjectVariableBoolean(h2,30): #Text hatte kein Platz if i < len(intersection_points_sorted)-2: #not last dimension start_next = intersection_points_sorted[i+1] #=endPt end_next = intersection_points_sorted[i+2] next_segment_length = abs(end_next - start_next) if prior_segment_length < threshold_2_dimension and next_segment_length > threshold_2_dimension: vs.SetObjectVariableBoolean(h2,29,False)#unlock Text position vs.SetObjectVariableReal(h2,44,-0.1)#text shift vs.SetObjectVariableBoolean(h2,29,True)#calculate dim text color = (65000,0,0); prior_shifted_up = False elif prior_segment_length < threshold_2_dimension and next_segment_length < threshold_2_dimension and prior_shifted_leftright == False: vs.SetObjectVariableBoolean(h2,29,False)#unlock Text position vs.SetObjectVariableBoolean(h2,30,True)#Text inside vs.SetObjectVariableReal(h2,44,-0)#text shift color = (0,30000,30000); prior_shifted_up = False elif prior_segment_length < threshold_2_dimension and next_segment_length < threshold_2_dimension and prior_shifted_leftright == True: vs.SetObjectVariableBoolean(h2,29,False)#unlock Text position vs.SetObjectVariableBoolean(h2,30,True)#Text inside if not prior_shifted_up: vs.SetObjectVariableReal(h2,43,offset_up); prior_shifted_up = True; color = (0,65000,0) vs.SetObjectVariableReal(h2,44,-0); color = (0,0,65000) else: vs.SetObjectVariableBoolean(h2,29,False)#unlock Text position vs.SetObjectVariableReal(h2,44,-0.1)#text shift vs.SetObjectVariableBoolean(h2,29,True)#calculate dim text prior_shifted_leftright = True else: prior_shifted_leftright = False #prior_segment_unshifted = vs.GetObjectVariableBoolean(h2,30) #debug if data['b_debug_dim_color']: vs.SetPenFore(h2, color) vs.ResetObject(h2); #vs.SetPenFore(h2, (65000,0,0)) vs.ResetObject(h1) h1 = vs.CreateChainDimension(h1, h2) else: #first dimension > move to left h1 = vs.LNewObj()#;vs.SetPenFore(h1, (65000,0,0)) if not vs.GetObjectVariableBoolean(h1,30): #Text hatte keinen Platz vs.SetObjectVariableBoolean(h1,29,False)#unlock Text position vs.SetObjectVariableReal(h1,44,0); if data['b_debug_dim_color']: vs.SetPenFore(h1, (30000,0,30000)) #vs.AlrtDialog(str(h1)) prior_segment_length = abs(end - start) start = end chain_dims.append(h1)
  23. Thanks for Feedback I will try with a DomMenuTextByName as a workaround, thanks The complete Script has 800 lines (it reaches the limit of maximum size of a script), take a look here 🙂 An incredible powerful Auto-Dimension Script The Second Script iterates through the length of dimensions. If I have the minimum of Objects (2) then length is 2 The loop starts with 0 and ends with 2-1 (1). If the loop would go till i == 1 i had an index of range with i+1. Different ways to do that with python.
  24. Hi there I want to join single dimensions in one chain dimension. So far it works but I have an undo issue. If I undo the script my single dimensions are deleted and I also get an undo alert in the log file. My simple test with two dimensions: h1 = vs.FSActLayer() h2 = vs.NextSObj(h1) hnew = vs.CreateChainDimension(h1, h2) My function to join n-Numbers of single dimensions dimensions = [] def getObj(h): dimensions.append(h) vs.ForEachObject(getObj, "(NOTINDLVP & NOTINREFDLVP & (SEL=TRUE))") h1 = dimensions[0] for i in range(len(dimensions)-1): h1 = vs.CreateChainDimension(h1, dimensions[i+1]) The Scripts are working on selected objects for that test. The Undo Alert I get: "ALERT: Invalid undo primitive detected: Imminent crash is possible. Object 0x7ff725723440 is being inserted after it has been modified or deleted.","type":"INFO"} Also really it is an undo issue because Unto after script deletes my dimensions. Have I to handle the undo events in a Vector Script?
  25. @corbinhand Have you already checked this out?
×
×
  • Create New...