-
Posts
645 -
Joined
-
Last visited
Content Type
Profiles
Forums
Events
Articles
Marionette
Store
Everything posted by DomC
-
I try to get the right selector for that menu Command vs.DoMenuTextByName('Update Selected Viewport', 0) Background is, that i fail with vs.UpdateVP() when i want to have hidden line render it somehow shows elements from hidden class. if i update viewport by menu it looks all right after that. I pasted some code but it is try and error code. In Main i 1. hide all classes 2. hide classes which are mandatory for object size 3. UpdateVP to measure size of the minimal vp crop size 4. show rest of classes i want to see 5. Update vp again I am sure, somewhere i had to reset a cache, an object variable etc. It works with Shaded View but not with hidden line. I just need a pragmatic solution so DoMenuTextByName whould do the job. code vp_handle = vs.CreateVP(layout_handle) set_vp_scale(vp_handle, scale) hide_classes_by_keword(vp_handle, 'RS_Mobiliar') #vs.UpdateVP(vp_handle) hide_classes_by_keword(vp_handle, 'RS_Wand-') ##_bool = vs.SetVPClassVisibility(vp_handle, 'RS_Mobiliar', -1) #vs.UpdateVP(vp_handle) class_name = 'RS_Wand-' + space_name + '_' + str(i) class_name_last = None class_wall = 'RS_Wand-' + space_name + '_gesamt' if i == len(segment_lengths) - 1: class_name_last = 'RS_Wand-' + space_name + '_' + str( i + 1) #_bool = vs.SetVPClassVisibility(vp_handle, class_name_last, 0) visible_classes = visible_classes_construction_netto + [class_name, class_name_last, class_wall] set_class_visibility(vp_handle, visible_classes, invisible_classes_construction_netto) _bool = vs.SetVPLayerVisibility(vp_handle, space_layer, 0) _bool = vs.SetEntityMatrix(vp_handle, (pos, 0,0), 0, 0, 0) vs.SetViewMatrix(vp_handle, (0,0,0), -90, -vertex_angles[i], 0) vs.SetObjectVariableInt(vp_handle, 1000, 0) vs.SetObjectVariableInt(vp_handle, 1001, 6) #hidden line background 1036 # hier sind Klassen ausgeblendet, die übger den VP hinausschauen. Damit die BBox sauber ist, muss das so aktualisiert werden vs.UpdateVP(vp_handle) vp_cache = vs.GetVPGroup(vp_handle, 3) tl, br = vs.GetBBox(vp_cache) w = br[0] - tl[0] bl = tl[0], br[1] vs.RectangleN(bl[0], bl[1], 1, 0, w, 4000) rect = vs.LNewObj() vs.SetPlanarRef(rect, 0) # Und hier kommen diese Klassen vom Rand wieder dazu. Z_.B. Eckv erbindung guckt ja auch überr die BBox der Wand raus oder Bemassungen _bool = vs.SetVPCropObject(vp_handle, rect) visible_classes = visible_classes_construction_final + [class_wall] set_class_visibility(vp_handle, visible_classes, []) set_vp_class_colors(vp_handle) vs.SetObjectVariableInt(vp_handle, 1001, 0) #wireframe vs.SetObjectVariableInt(vp_handle, 1001, 6) #hidden line #vs.SetObjectVariableInt(vp_handle, 1006, 0) #foreground #vs.SetObjectVariableInt(vp_handle, 1036, 3) #hidden line ovViewportForegroundRenderType 1036 #vs.UpdateVP(vp_handle) #vs.SetObjectVariableInt(vp_handle, 1036, 6) #hidden line ovViewportForegroundRenderType 1036 #vs.ResetObject(vp_handle) vs.SetObjectVariableBoolean(vp_handle, 1167, True) vs.ResetObject(vp_handle) vs.UpdateVP(vp_handle) vs.ReDraw() #vs.HMove(vp_handle, pos, 0) l = w / scale #(segment_lengths[i] + 68) / scale vp_list.append([vp_handle, l, i, vertex_angles[i]]) What it does: Taking the modell After vs.UpdateVP i have the result "Before Update". After Menu Command Update i have result "After Update" I Tried a lot (vs.SetObjectVariableBoolean(vp_handle, 1167, True) etc. ) but seems not the right things ...
-
Clever and elegant. Thanks for that input!
-
OK, i solved like this (maybe still errors but so far is should work like this): A column with the last publishing date: =VERKETTEN(IF('Title Block Issue Data-1'.'Date'<>'', 'Title Block Issue Data-1'.'Date', IF('Title Block Issue Data-2'.'Date'<>'', 'Title Block Issue Data-2'.'Date', IF('Title Block Issue Data-3'.'Date'<>'', 'Title Block Issue Data-3'.'Date', IF('Title Block Issue Data-4'.'Date'<>'', 'Title Block Issue Data-4'.'Date', IF('Title Block Issue Data-5'.'Date'<>'', 'Title Block Issue Data-5'.'Date', '-')))))) And then a column for comparison the last Revision with the publishing date: =IF(TEILSTRING('Title Block Revision Data-1'.'Date', '.', 1)>TEILSTRING(M5, '.', 1), 'neu', IF(TEILSTRING('Title Block Revision Data-1'.'Date', '.', 2)>TEILSTRING(M5, '.', 2), 'neu', IF(TEILSTRING('Title Block Revision Data-1'.'Date', '.', 3)>TEILSTRING(M5, '.', 3), 'neu', 'alt'))) TEILSTRING is same as SUBSTRING
-
Hi Somebody have experience converting the date string into a number? I want to 1. Compare and take the last Date. Which also works like this but is not very elegant: =IF('Title Block Issue Data-1'.'Date'<>'', 'Title Block Issue Data-1'.'Date', IF('Title Block Issue Data-2'.'Date'<>'', 'Title Block Issue Data-2'.'Date', IF('Title Block Issue Data-3'.'Date'<>'', 'Title Block Issue Data-3'.'Date', IF('Title Block Issue Data-4'.'Date'<>'', 'Title Block Issue Data-4'.'Date', IF('Title Block Issue Data-5'.'Date'<>'', 'Title Block Issue Data-5'.'Date', '-'))))) 2. I want to compare revision is newer than approved I could split the date into year, month and day and then compare each to find if one is newer than the other. But maybe there is a direct way to convert a date into a number? i already tried int('Datestring') with different formats m/y/d, d/m/y etc. but that seems to fail Edit: It works with a plain cell with a date string. But not yet with a calculated date.
-
-
Hi My idea is to create a web server, host a dialog there, and exchange data via the web directory of the hosted content. So far, I see the following possibilities: 1. **Dump the site from Vectorworks to a local file.** Local web content is restricted and, as far as I can see, cannot contain cross-references or multiple files. This is for security reasons, as a web application shouldn't control the local file system. One way to address this is by using a local development server (e.g., Python's `http.server`) to serve the content over HTTP, bypassing these restrictions. 2. **Launch an Apache server on macOS.** This works so far; the site is hosted in a machine directory that is accessible with root privileges. It's quite simple to do with a `subprocess sudo apachectl start`. This would work, and the web application could load and write data in the directory. However, this requires root access to start Apache. Or having to manipulate configuration files. 3. **Launch a web server via Python.** Here, it’s not possible to launch it directly within Vectorworks because the server would block the Vectorworks main thread, as Python’s default HTTP server runs synchronously. 4. **Launch a Python web server as a subprocess and access the embedded Python in Vectorworks.** This could be possible, but the environment variables in the OS might not handle the embedded Python properly. Explicitly configuring the subprocess environment or using isolated Python installations could help mitigate this issue. However, it's possible that the embedded Python content is designed to run exclusively within Vectorworks, making this option challenging. bash python3 -m http.server 8080 5. **Installing additional application in the OS.** This is also possible, but the solution should work like a portable standalone application rather than requiring content to be installed into the system. Tools like Docker or portable Python distributions could make this approach feasible without impacting the system setup. 6. **Using an external web application to handle everything.** In this approach, you send a token, the web application processes the data (e.g., sanitizes and validates it), builds the site, and writes results to a database. The local script can then retrieve the results using the temporary token. I’ve used this method for some projects, and it seems very flexible and powerful. However, it requires an external web service and isn’t lightweight at all. 7. Creating one single local web-page Merging everything in one file would work for pushing the content into the site. Still the issue then, that it is not possible to write something on the disk, which would work with the #2 apache webservice. I know an SDK-developed application could make direct access possible (anyway i never tried this, too much respect from the c++ environment), even with a non-blocking palette. But still there is the other question of hosting the site on the localhost. Does anyone have additional ideas for a simple, secure and clean workflow to host the web-content?
-
Got it vs.SetDLSeparation(separationDistance)
-
Hi What i am trying to do is, change tool settings by script. The Following approaches i try: 1. SetSavedSetting() This works, but it seems it writes to the xml memory. And while closing Vectorworks the settings are wrote back to the file. Also i can set every setting i want as Example vs.SetSavedSettings('foo', 'bar', 100) It will store that setting 2. Second approach Writing the xml file. Which also works. It writes the value with my example. But after closing Vectorworks it will overwrite with the tool setting. any ideas? import os import xml.etree.ElementTree as ET # Hauptskript user_app_settings = vs.GetFolderPath(-15) tool_settings_file = os.path.join(user_app_settings, 'SavedSettings.xml') s_dialog = 'Einstellungen optimieren' #res = vs.YNDialog(s_dialog) import xml.etree.ElementTree as ET def modify_nested_xml_value(file_path, parent_tag, key, new_value): # Parse the XML file tree = ET.parse(file_path) root = tree.getroot() # Suche nach dem übergeordneten Tag und dann nach dem spezifischen Element innerhalb davon parent = root.find(f".//{parent_tag}") if parent is not None: element = parent.find(key) if element is not None: element.text = str(new_value) # Setze den neuen Wert # Speichere das aktualisierte XML zurück in die Datei tree.write(file_path, encoding="UTF-8", xml_declaration=True) vs.Message(f"Updated '{key}' under '{parent_tag}' to '{new_value}' in {file_path}") parent_tag = "DoubleLinePreferences" key = "Separation" new_value = "19" # Neuer Wert für Separation modify_nested_xml_value(tool_settings_file, parent_tag, key, new_value) vs.SetSavedSetting('DoubleLinePreferences', 'Separation', 20) res = vs.GetSavedSetting('DoubleLinePreferences', 'Separation') vs.AlrtDialog(str(res))
-
The node is called color input not color rgb Normally the issue of disappearing objects it the 2D 3D Content that a PIO or a Symbol can have (do you have a PIO?) It also depends if you have screen plane or layer plane as default, where your 2D Objects are places inside a PIO. For better control of where Planar Objects are placed you can use Set Planar ref (0 is screen plane and will be 2D Component of PIO) or set component group. Also discussed here.
-
1. The Compose node uses a Menu-Command. It works as long as it is not used inside a PIO Object. The reason why it does not work is, that you do not create any lines which you could compose. Lines: 2. You try to create lines with start 0.0 and end 350.0. Instead you should insert a point (0.0,0.0) at start and end(350.0,350.0) as Example. 3. You have a list of points in the right order. You could create directly a polygon with the node "Create 2D Poly" Here two Variants to create the polygon. I would choose Variante B it the rest of the network do not need lines somewhere. Just the poly This two Rectangles creates the same Polygon I mean 4 Nodes agains one single nodes which does the same (I counted the Attribute node in the Screenshot)
-
Version 1.0.0
32 downloads
This node is the end of boring QR codes that anyone can make. With this node, the creative designer creates their own QR codes. There are endless design possibilities. But be careful: at some point, the QR code may no longer be readable by your smartphone. How it works: Enter the text (e.g., URL link) in the info palette, press Enter > done. Have fun with it! How it works: Enter the text (e.g., URL link) in the info palette, press Enter > done. Have fun with it! -
Version 1.0.0
47 downloads
This is an older but still fantastic marionette. The thing which is a little newer is the version of the poeple Crowd polygon which i never shared i think. With the following Features: 1. One big Focus Point where people crowding (Entrance, Food Track etc.) 2. Smaller Focus Points where people talk together etc. 3. The Script gets different symbol folders. It collects from a folder symbols in the focus arreas (waiting people, sitting people as Example) 4. Ant a different Folder for People which moving between the focus points To Make your people layout, you could combine more than one PlugIns with different settings. I think you need one PlugIn per Special Focus. i think this could also be used for trees, cows and other living objects. -
With look you mean the Attributes or the algorithm? 1. Well the Attributes depends on the classes and the classes depends on the different name of the matrial you have in your list. If you create the classes first, you can define the attributes before the script runs. 2. The Packing algorithm and settings of the PIO defined in the pio. You could test your settings first with a smaller list by input a smaller copy of your worksheet. And then for final calculation link your real-list. While it is a plug in you can only change one parameter at a time. It will recalculate after every change. Also maybe sort your list by materials. So you can work in etapes. 3. To prevent this. For your usecase you could double click the PIO, edit the script. copy the network. Then close file and reopen (because recalculation of script could take a while) then paste the script on the construction layer. Here you can change as many inputs values as you want and run the network manually. The script should run ourside the PIO without modifications, just delete the big rectangle in the background after creation
-
@Zuzzla Thanks for noting that. After all this is right. The node uses the key varName which represent the internal name. the key 'text' represents the visible parameter name. Because i use "if name in varName" and not name == varName it worked for me while i always not check with the full name. However the "text" key was the right one to use.
-
VS:SetComponentName doesn't change componentname
DomC replied to matteoluigi's topic in Python Scripting
If so i would not just loop the walls in drawing and changing the same stile hundreds of times. I would get the walls and collect the used style names. Then i would eliminate duplicate names and loop the style names. Or collect the Resources directly. Beside that, i would not change object swhich i collect with "ForEachObject" directly in the "ForEachObject" callback function. I would use "ForEachObject" always as a read only manipulation. something like this: wall_style_names = [] def get_objects(h): wall_style_name = vs.GetWallStyle(h) '''hinzufügen, falls nicht schon in der Liste''' wall_style_names.append(wall_style_name) if wall_style_name not in wall_style_names else None vs.ForEachObject(h,('T=WALL')) for wall_style_name in wall_style_names: wall_style_handle = vs.GetObject(wall_style_name) '''security to be sure just manipulating wall styles''' if vs.GetTypeN(wall_style_handle) == 127: #Do your component renaming code here -
VS:SetComponentName doesn't change componentname
DomC replied to matteoluigi's topic in Python Scripting
Short Test. It works with an unstyled Wall. h = vs.FSActLayer() bool = vs.SetComponentName(h, 1, 'ciao') For a Styled Wall, it works by get handle of wall style and set it there: -
VS:SetComponentName doesn't change componentname
DomC replied to matteoluigi's topic in Python Scripting
I think it is not possible the change the component name of a styled wall. Even manually we are not able to do so. Text is greyed out -
1. Table with output boards would be possible by enhancing the script. But never heard before of that because you count the needed boards very fast. Also on your file. You need less than one board for every material. For what usecase this would be needed, would it save time or is it prevent misscounting? 2. Graphical Attributes. For ever Material autmatically a class is created and you can just change the class style to change the attributes. Note you have some Workpieces without a Material You have a class for Platten (Boards) and Teile (Parts). For the Text you had a Text-Style, but you deleted. Take it back from the Template. Then you can set Text Size and Text centered etc. Best looking Optimizing Software ever 🙂
-
VS:SetComponentName doesn't change componentname
DomC replied to matteoluigi's topic in Python Scripting
Not near my Mac. I Wonder if you handle the style or the Wall. -
How to assign a texture to a 3D object (Solved)
DomC replied to Carles Olle's topic in Python Scripting
was not able to wait and solved it with a funktion: def get_longest_direction(final_contour): # Define the contour points # Calculate the centroid (center) of the contour centroid_x = sum(point[0] for point in final_contour) / len(final_contour) centroid_y = sum(point[1] for point in final_contour) / len(final_contour) # Initialize variables to keep track of the longest edge and its direction max_distance = 0 direction = '' longest_edge_points = () # Iterate over the points to calculate x and y distances between consecutive points for i in range(len(final_contour)): # Get the current point and the next point in the list (wrapping around at the end) x1, y1 = final_contour[i] x2, y2 = final_contour[(i + 1) % len(final_contour)] # Calculate the x and y distances x_distance = abs(x2 - x1) y_distance = abs(y2 - y1) # Check if x distance is the longest so far if x_distance > max_distance: max_distance = x_distance direction = 'x' longest_edge_points = ((x1, y1), (x2, y2)) # Check if y distance is the longest so far if y_distance > max_distance: max_distance = y_distance direction = 'y' longest_edge_points = ((x1, y1), (x2, y2)) # Determine the position of the longest edge relative to the centroid (x1, y1), (x2, y2) = longest_edge_points # Check the relative position of the longest edge if direction == 'x': if centroid_y > y1: # Edge is below the centroid position = 'below' else: # Edge is above the centroid position = 'above' elif direction == 'y': if centroid_x > x1: # Edge is to the left of the centroid position = 'left' else: # Edge is to the right of the centroid position = 'right' return position longest_direction = get_longest_direction(final_contour) '''and for the mapping this code''' vs.SetDefaultTexMapN(rec, 3, 0) vs.SetTextureRefN(rec, texRef, 0, 0) # flip horizontal #vs.SetObjectVariableInt(rec, 540,1) vs.SetTexMapBoolN(rec, 3, 0, 7, False) vs.SetTexMapBoolN(rec, 3, 0, 5, False) #texture part, overall is 3. Selector: init:1, flip:2, repH:3, repV:4, long edge:5, worldZ:6, auto align:7 angle = 0 if 'links' in c: if longest_direction == 'left': angle = -90 * (pi / 180) if longest_direction == 'right': angle = 90 * (pi / 180) elif longest_direction == 'above': angle = 180 * (pi / 180) if 'rechts' in c: vs.SetTexMapBoolN(rec, 3, 0, 2, True) if longest_direction == 'left': angle = -90 * (pi / 180) if longest_direction == 'right': angle = 90 * (pi / 180) elif longest_direction == 'above': angle = 180 * (pi / 180) vs.SetTexMapRealN(rec, 3, 0, 4, angle) -
How to assign a texture to a 3D object (Solved)
DomC replied to Carles Olle's topic in Python Scripting
Hi Searched the Forum but did not found another thread about the textur mapping: 1. I have attach a textur on an extrude. The Extruse can have 4 or more vertex points of a 2D Poly 2. Starting point is alsways the same and also the direction is known. Main question is, how to prevent texture mapping from aligning to the longes vertex of the face? I use as example this, to rotate, which works. Also Flipping is working vs.SetTexMapRealN(rec, 3, 0, 4, angle) I tried this but this does not change the mapping vs.SetTexMapBoolN(rec, 3, 0, 7, False) vs.SetTexMapBoolN(rec, 3, 0, 5, False) What i do now is, i get the bound in x and y (view on the face) and then rotate by 90 degrees if the y is bigger than y so texture would stay horizontal aligned to the world coordinates , which works for rectangular shapes. I now have to deside if i analyse the shape (if shape is not rectangular) for the longest edge or if there would be an existing function for that. My testing code looks like this: vs.SetDefaultTexMapN(rec, 3, 0) vs.SetTextureRefN(rec, texRef, 0, 0) # flip horizontal #vs.SetObjectVariableInt(rec, 540,1) vs.SetTexMapBoolN(rec, 3, 0, 7, False) vs.SetTexMapBoolN(rec, 3, 0, 5, False) #texture part, overall is 3. Selector: init:1, flip:2, repH:3, repV:4, long edge:5, worldZ:6, auto align:7 angle = 0 ''' if 'links' in c: if breite < h: angle = 90 * (pi / 180) else: if len(final_contour) < 5: #Rechteck angle = 180 * (pi / 180) else: angle = 180 * (pi / 180) ''' if 'rechts' in c: vs.SetTexMapBoolN(rec, 3, 0, 2, True)#flip vertical axes '''texture is aligning not to the bounds it aligns to single edges of object''' if breite < h: angle = 90 * (pi / 180) else: if len(final_contour) < 5: #Rechteck #vs.AlrtDialog(tex_name) angle = 180 * (pi / 180) else: #vs.AlrtDialog(tex_name) angle = 0 vs.SetTexMapRealN(rec, 3, 0, 4, angle) #vs.SetTexMapBoolN (rec,3,0,3,True) #vs.SetTexMapBoolN(rec, 3, 0, 2, False)#flip vertical axes #vs.SetTexMapBoolN(rec, 3, 0, 2, True)#flip horiz axes res = vs.SetEntityMatrix(rec, (ps[0], ps[1], 0), 90,0,b) vs.SetClass(rec, c) Short movie which shows, that the texture changes alignment if another edge is getting the longest edge. Auto-Texture-Align.mp4 -
Yes it should be possible. If you edit the script you find the string input for the feald name of the area Since 2024 it is a new field (MeasuredNetAreaNum) you can see the right field names with a worksheet as example. In past i did used other fields but i think i never used the grossArea (BruttoFläche) Field. The Field MeasuredNetAreaNum is a special Field which is compatible with Vectorscript and has not to be parsed from a string to a number which created so many troubles in past version (while the biggest time consume of the script was the game, how to convert a Text like "1.045,186m2" (which can be different for every document settings, and country settings of the computer) in a number like 1045.2?) Just to say, why i recommend to use one of the field with ... Num at the End. This can be converted to a Number in a reliable way by the custom Marionette Node Str2Num from the Wohnungsstempel Marionette.
-
Hi Create Additional (dynamic or non dynamic Field) in the Tag: 1. Edit Record Format and create new field 2. Edit Symbol and link new Textfield to that new Record Field 3. Edit the Script and link an input or a computed value to that record field Exit the Script Style and then you should have a new input Field. Importand. Edit the right Symbol, which you use in the Wohungsstempel.
-
Create a texture resource from image in a folder
DomC replied to jonasfehr's topic in Python Scripting
I'm as happy as a little child right now! I just made a short movie to show what I can use this for. It allows practically a real-time exchange of wall textures, which can be accessed from a shared location or via web API. The customer can see their printable areas directly with a pre-prepared image file, and I can visualize his demands in real-time. REAL-TIME-VISUALISATION :-))) import image texture.mp4