Jump to content

DomC

Member
  • Posts

    604
  • Joined

  • Last visited

Posts posted by DomC

  1. Hello

    I have a PIO with Button-Widgets. One of them should convert the PIO in another PIO and back. Is it possible to delete the PIO with the Button at all?
     

    	elif theButton == cButton6:
    		if replace_object():
    			vs.DSelectAll()
    			vs.SetSelect(GlobalValues.pio_handle)
    			vs.AlertInform('Press delete after action to delete original object', '','') #This would work so far
    			vs.DelObject(GlobalValues.pio_handle) #This wont work (and if it would work i think it may result in a crash?)

     

  2. Hi
    Did not looked into your code details because i keep that theme for a time from my brane. 
    I think the general we can take an objects entity matrix and set that entity matrix to another object. With Set- and get Entity Matrix. This is not really hard. What was always the point is, that having some points in 3D which defines a plane transferring to an entity matrix wen need for the SetEntityMatrix Script command. 

    What i have so far in that direction:
    1. A way to have 3 points and gets an VW entity matrix of 3 points. Somehow my code os spreaded over a bigger code so i do now know if exactly that works in your example. code and functions i needed there code snippeds.

    I would say the code here took me several hours of figuring out that easy looking code. But i think at the end it maybe needs just a few lines if it was optimated. Also the vs.Vec2Ang() solves a lot. It would be hard to find out in which quadrant the plane is oriented and the direction of the points etc..

    Like i told, not looked yet into your code. This snipped worked here for getting rotation matrix from 3 points. Not sure, if it works in all directions and for vertical planes in every situation. I always thought there must be a general solution for that. And there is but on the other side we must fit it to the vw SetEntity matrix also the plane matrix are different from the rotation matrix. 

    image.png.edf964fe938a7035d728528cf866860e.png

    2. Getting a centroid and a plane. With that we can project points on that plane (not a vw plane, a plane defined by the normal matrix of the custom getPlane Node in that example). Here:


    At one point everything is turning into hard work. But we still have fun 🙂

     

  3. Initially the issue is, that putting geometry into the profile group it is centered to the mid point (Even if you move profile before you create path it does not matter, it will be centered independent from its coordinates, thats why we have to move AFTER creation of path extrude). I am not sure anymore, why i used that locus point to get offset of the profile group(if you know the offset of the reference point to the middle of the profile you do now use locus point you can just move the profile by a known value). Reseting path extrude after moving the profile inside, is definitely still necessary in my opinion.

    • Like 1
    • Love 1
  4. Hello
    Sorry kinda occupied at the moment. The vs.ResetObject(x) will do reset at the end of a script i guess. So when it it duplicated it duplicates the unreseted state of the object and converting to mesh deletets the path position which is not reseted.
     

    What you can do, is a "hard reset" by using 

    vs.SetObjectVariableBoolean(x, 1167, True)

    instead of vs.ResetObject(x)

    image.png.9b5cc5f51c05eff4e725e52532d1e702.png

    As far as i notice by changing the reset node it would keep the mesh in position. Hope that works for you

    • Love 1
  5. Agreed, class organization is still a crucial aspect, often posing challenges for users. Not all offices and projects require the same workflows. In the realm of Big Projects, the class structure may deviate from the standard, evolving over several years, and copying from old drawings might not be a significant concern.

     

    On the whole, it appears to be the right approach to employ a management tool that seamlessly connects various elements. This functionality seems to be already present in Vectorworks and is working quite effectively but always open for future improvements. We have the Ebenen/Klassen-Manager tool and/or the class/layer mapping feature. These tools allow users to define class mappings and save/load them for use in different projects. While mapping classes during object pasting might be functional, it does not align perfectly with the broader workflow requirements addressed by the aforementioned features, such as inserting resources and importing geometry.

    Try thinking one step forward i can imagine, that something like a overall document style (Not just for classes, mybe also central saved values as project data etc. - i think styles are really a great working concept) could be worth thinking about in this direction.

    image.png.2fbc63cce9afe293ccd8f06faee22d31.png
    image.png.8d05cf92ba317d8bdbaefa0712db6d97.png


    However:

    Admittedly, I have not insight to "smart paste" feature in action, so my assumptions may be incorrect. It appears that this command executes a standard "paste" action initially, followed by a dialog that enables the user to modify the class of the pasted elements within a selected class, while also offering the option to delete newly created classes if undesired. Due to potential reliance on legacy commands or an inaccessible included file, the functionality may no longer be operational. Generally, scripts can be normally easily adapted for new versions, even when some functions are outdated. But the script does not seems to be available anymore?
     

    I use a similar script for records, i invested some time to fit to the class requirements. The script saves the substitution dictionary on disk, a feature seemingly unsupported by the old function. This script appears to encompass approximately 30% of the original "smart paste" pascal-script and its associated included file. It suggests that a fundamental element may be missing or that the dialog code in my example is more concise due to the dynamic creation of the object without the use of dialog builder components.




    The Dialog of my script:
    image.thumb.png.67b1d2948fcb5d07ec92331056a5078b.png

    image.png.866e1fa95578f28d03d107998b1b3445.png

    '''
    DomC 26.12.2023
    
    Disclaimer:
    This script comes with no warranty or official support services (excluding the Community Forum). Use at your own risk. It is recommended to test with a copy of your original documents.
    
    Known Issues:
    - Some content within symbols or PIOs may lead to unexpected results.
    - Pasted resources, including colors, symbols, line types, dimension standards, etc., are not translated; only classes are affected.
    - The script performs an all-encompassing paste action, resulting in a change to the pastes, still selected elements after pasting.
    - Pasting inside annotations, Symbols, PIO Graphic Containers etc. may result in unexpected results.
    - If a bug occours no pasted objects should be missed. Just maybe in wrong classes or maybe unwanted classes are deleted at the worst case.
    - This script is proof of concept and not matured by testing in real environment
    
    The script manages settings using a JSON file (smart_paste_settings.json).
    It provides functions to read and write a dictionary of class translations from and to the JSON file.
    Class Management:
    
    It defines functions to get a list of existing class names in the document and find the difference between two lists of classes.
    After a Paste operation (vs.DoMenuTextByName('Paste', 0)), it identifies new classes.
    Dialog Interface:
    
    If the debug_dialog flag is set to True, a predefined list of new classes is used for testing the dialog.
    The script creates a dialog that allows the user to interactively manage class translations.
    The dialog includes options to paste all into the active class, view classes present in the dictionary, substitute classes in the dictionary but not in the drawing, and handle new classes not yet in the dictionary.
    Dialog Functionality:
    
    The dialog provides an organized interface with columns for the original class name, the last translated class, and a dropdown menu for selecting a new class.
    It includes color-coding for clarity (blue for in the dictionary, green for in the drawing but not in the dictionary, red for not in the dictionary).
    Users can save their settings using a checkbox.
    Undo Mechanism:
    
    If the dialog is canceled, the script performs an Undo operation (vs.DoMenuTextByName('Undo', 0)).
    Post-Dialog Processing:
    
    After the dialog, if saving settings is enabled, it updates the JSON file with the new class translations.
    It handles the class translations for pasted objects, updating their classes according to the user's selections.
    It identifies classes to delete based on the difference between new classes and those in the class dictionary.
    Overall, the script provides a user-friendly interface for managing class translations, making it easier to handle classes in a Vectorworks document.
    '''
    
    import vs
    import os
    import json
    
    # Set the folder and file paths for the settings
    settings_folder = os.path.join(vs.GetFolderPath(-15), 'smart_paste')
    settings_file = os.path.join(settings_folder, 'smart_paste_settings.json')
    
    # Set debug mode (True for debugging, False otherwise)
    debug_dialog = False
    
    # Get the active class name
    active_class_name = vs.ActiveClass()
    
    # Function to read settings from a JSON file
    
    
    def read_settings(settings_folder, settings_file):
    	# Create the settings folder if it doesn't exist
    	if not os.path.isfile(settings_folder):
    		os.makedirs(settings_folder, exist_ok=True)
    
    	try:
    		# Read the class dictionary from the settings file
    		with open(settings_file, 'r', encoding='utf-8') as file:
    			class_dictionary = json.load(file)
    
    	except:
    		# If an error occurs during reading, set an empty dictionary
    		class_dictionary = {}
    
    	return class_dictionary
    
    # Function to write settings to a JSON file
    
    
    def write_settings(settings_folder, settings_file, class_dictionary):
    	# Create the settings folder if it doesn't exist
    	if not os.path.isfile(settings_folder):
    		os.makedirs(settings_folder, exist_ok=True)
    
    	try:
    		with open(settings_file, 'w', encoding='utf-8') as file:
    			file.write(json.dumps(class_dictionary,
    					   ensure_ascii=False, indent=2))
    
    	except:
    		# If an error occurs during writing, display an alert dialog
    		vs.AlrtDialog('Error writing setting File')
    
    # Function to get all class names in the document
    
    
    def get_class_names():
    	out_classes = []
    	num_class = vs.ClassNum()
    	for i in range(1, num_class + 1):
    		cname = vs.ClassList(i)
    		out_classes.append(cname)
    
    	return out_classes
    
    # Function to find the difference between two lists of classes
    
    
    def class_diff(old_list, new_list):
    	return [c_new for c_new in new_list if c_new not in old_list]
    
    
    # Read existing translation from the settings file
    class_dictionary = read_settings(settings_folder, settings_file)
    
    # Get existing class names in the document
    existing_classes = get_class_names()
    
    # Perform a Paste operation
    vs.DoMenuTextByName('Paste', 0)
    
    # Get existing class names after pasting
    actual_classes = get_class_names()
    
    # Get new classes after pasting by finding the difference
    new_classes = class_diff(existing_classes, actual_classes)
    
    
    # class list for testing dialog
    if debug_dialog:
    	new_classes = [
    		"Lorem ipsum",
    		"Unknown Class1",
    		"Dolor sit am",
    		"Consectetur",
    		"Adipiscing",
    		"ClassNotInDictionary",
    		"Elit",
    		"Sed do eiusm",
    		"Unknown Class2",
    		"Tempor",
    		"Incididunt ut",
    		"Labore et",
    		"Dolore magna",
    		"Aliqua",
    		"Ut enim ad",
    		"Minim veniam",
    		"Quis nostrud",
    		"Exercitation",
    		"Ullamco",
    		"Laboris",
    		"Duis aute",
    		"Reprehenderit",
    		"Voluptate",
    		"Velit esse",
    		"Cillum",
    		"Excepteur sint",
    		"Proident",
    		"Culpa qui",
    		"Aenean commodo",
    		"Massa quis",
    		"Enim justo",
    		"Rhoncus ut",
    		"Integer",
    		"Tincidunt",
    		"Cras dapibus",
    		"Vivamus",
    		"Elementum",
    		"Aenean vulpu",
    		"Aliquam lorem",
    		"Phasellus",
    		"Fermentum",
    		"Viverra quis"
    	]
    
    items_left = []
    items_middle = []
    items_right = []
    translate_list = []
    saved_settings = {}
    
    
    def dialog_settings():
    	# Control IDs
    	kOK = 1
    	kCancel = 2
    
    	# UIAskForStringsToReplace
    	def CreateDialog():
    		# Alignment constants
    
    		# Create the main dialog layout
    		dialog = vs.CreateLayout(
    			'Class Substitute', False, 'OK', 'Cancel', True)
    
    		# Create controls and set their positions
    		vs.CreatePushButton(dialog, 5, 'Paste all in active class.')
    		vs.SetFirstLayoutItem(dialog, 5)
    		vs.CreateStaticText(dialog, 6, 'new_class present in dictionary', 30)
    		vs.SetStaticTextColorN(dialog, 6, 0)
    		vs.SetBelowItem(dialog, 5, 6, 0, 1)
    		vs.CreateStaticText(dialog, 7, 'substitute class in dictionary but not in drawing', 40)
    		vs.SetStaticTextColorN(dialog, 7, 4)
    		vs.SetRightItem(dialog, 6, 7, 0, 0)
    		vs.CreateStaticText(dialog, 8, 'new class not yet in dictionary', 30)
    		vs.SetStaticTextColorN(dialog, 8, 2)
    		vs.SetRightItem(dialog, 7, 8, 0, 0)
    		vs.CreateStaticText(dialog, 9, 'Existing class manually attached', 30)
    		vs.SetStaticTextColorN(dialog, 9, 3)
    		vs.SetRightItem(dialog, 8, 9, 0, 0)
    
    		# Script Scope Variable initialization
    		max_lines = 20
    		num_groups = int(len(new_classes) / max_lines + 1)
    		kgroup_list = []
    		start_id = item_id = 12
    		class_counter = 0
    		kgroup_list = []
    
    		for i in range(num_groups):
    			# Create a group for each set of classes
    			item_counter = 1
    			group_name = 'List ' + str(i)
    			vs.CreateGroupBox(dialog, item_id, group_name, False)
    			kgroup_list.append(item_id)
    			last_item = item_id
    			item_id += 1
    
    			for c_index in range(class_counter, len(new_classes)):
    				c_new = new_classes[c_index]
    				if class_counter >= max_lines * (i + 1):
    					break
    
    				# Check if the class is in the dictionary and set text styles accordingly
    				in_dict = False
    				in_dict_butnot_drawing = False
    
    				if c_new in class_dictionary:
    					in_dict = True
    					last_choice = class_dictionary[c_new]
    					if last_choice not in existing_classes:
    						in_dict_butnot_drawing = True
    
    				text_style = 2  # 2blue, 3green, 4red, 0black
    
    				if in_dict:
    					text_style = 0
    					if in_dict_butnot_drawing:
    						text_style = 4
    
    				else:
    					class_dictionary.update({c_new: active_class_name})
    					text_style = 2
    
    				last_choice = class_dictionary[c_new]
    
    				# Create static texts for class names and last choices
    				vs.CreateStaticText(dialog, item_id, c_new, 65)
    				vs.SetStaticTextColorN(dialog, item_id, text_style)
    
    				if item_id == kgroup_list[-1] + 1:
    					vs.SetFirstGroupItem(dialog, kgroup_list[-1], item_id)
    				else:
    					vs.SetBelowItem(dialog, last_item - 2, item_id, 0, 1)
    
    				last_item = item_id
    				item_id += 1
    
    				vs.CreateStaticText(dialog, item_id, last_choice, 65)
    				vs.SetStaticTextColorN(dialog, item_id, text_style)
    				vs.SetRightItem(dialog, last_item, item_id, 0, 0)
    
    				last_item = item_id
    				item_id += 1
    
    				vs.CreateClassPullDownMenu(dialog, item_id, 25)
    				vs.SetStaticTextColorN(dialog, item_id, text_style)
    				vs.SetRightItem(dialog, last_item, item_id, 0, 0)
    
    				last_item = item_id
    				item_id += 1
    
    				item_counter += 3
    				class_counter += 1
    
    			item_counter += 1
    
    		# Create a tab control for better organization
    		vs.CreateTabControl(dialog, 10)
    		vs.SetBelowItem(dialog, 6, 10, 0, 5)
    
    		for id in kgroup_list:
    			vs.CreateTabPane(dialog, 10, id)
    
    		# Create a checkbox for saving settings
    		last_item = item_id
    		item_id += 1
    		vs.CreateCheckBox(dialog, item_id, 'Save Settings')
    		saved_settings['id_save'] = item_id
    		vs.SetBelowItem(dialog, 10, item_id, 0, 2)
    
    		return dialog
    
    	# Dialog handler function for dialog interactions
    	def DialogHandler(item, data):
    		if item == 12255:  # Enter Dialog
    			pass
    
    		if item == 5:
    			# Update middle column with the active class name for all classes
    			for id_middle in items_middle:
    				vs.SetItemText(dialog, id_middle, active_class_name)
    				vs.SetStaticTextColorN(dialog, id_middle, 3)
    				class_dictionary[vs.GetItemText(
    					dialog, id_middle - 1)] = active_class_name
    
    		if item in items_right:
    			# Update the right column with the selected class name
    			item_text = vs.GetItemText(dialog, item)
    			vs.SetItemText(dialog, item - 1, item_text)
    			vs.SetStaticTextColorN(dialog, item - 1, 3)
    
    			if item_text not in existing_classes:
    				vs.SetStaticTextColorN(dialog, item - 1, 4)
    
    			class_dictionary[vs.GetItemText(dialog, item - 2)] = item_text
    
    		if item == kOK:
    			# Save settings if the checkbox is selected
    			saved_settings['save'] = vs.GetBooleanItem(
    				dialog, saved_settings['id_save'])
    
    			# Store translation information in a list
    			for id_left, id_middle, id_right in zip(items_left, items_middle, items_right):
    				c_old = vs.GetItemText(dialog, id_left)
    				c_new = vs.GetItemText(dialog, id_middle)
    				c_last = vs.GetItemText(dialog, id_right)
    				translate_list.append([c_old, c_new, c_last])
    
    			return kOK
    
    	# Initialize variables and run the dialog
    	result = False
    	dialog = CreateDialog()
    
    	if vs.RunLayoutDialogN(dialog, DialogHandler, True) == kOK:
    		result = True
    
    	return result
    
    
    result = True
    if len(new_classes) > 0:
    	result = dialog_settings()
    	if result:
    		# Check if saving settings is enabled
    		if saved_settings['save']:
    			# Write updated settings to the settings file
    			write_settings(settings_folder, settings_file, class_dictionary)
    
    		# Initialize a list to store pasted objects
    		pasted_objs = []
    
    		# Function to add handles to the list
    		def add_handle(h):
    			pasted_objs.append(h)
    
    		# Get the active layer and its name
    		lh = vs.ActLayer()
    		ln = vs.GetLName(lh)
    
    		# Define criteria for selecting objects based on the active layer name
    		c = "(INSYMBOL & INOBJECT & NOTINDLVP & NOTINREFDLVP & ((L='ldummy') & (SEL=TRUE)))"
    		c = c.replace('ldummy', ln)
    
    		# Use ForEachObject to collect handles of selected objects
    		vs.ForEachObject(add_handle, c)
    
    		# Loop through the pasted objects and update their classes
    		for obj in pasted_objs:
    			old_class = vs.GetClass(obj)
    			new_class = class_dictionary.get(old_class, 'None')
    			vs.SetClass(obj, new_class)
    
    		# Identify classes to delete
    		classes_to_delete = []
    		for class_n in new_classes:
    			if class_n not in class_dictionary.values():
    				classes_to_delete.append(class_n)
    
    		# Delete identified classes
    		for class_name in classes_to_delete:
    			vs.DelClass(class_name)
    
    
    if not result:
    	vs.DoMenuTextByName('Undo', 0)



    For testing purposes this Marionette can be helpful to train the dictionary.



    Not really tested in real-application. @matteoluigi you see potential to take over the existing script?


    Test Classes.vwx

    • Love 2
  6. Update:
    After Working a little more in this environment and Drawing some Modells. I see a little better the lag in user-interaction. Not slow but the little lag, that would let us loos a game or missing the string of a guitar. I short: Nothing  for Vectorworks Artists ... 

    Also i see, that some (loved) tools (Ähnliches Aktivieren) and menu commands (Edit Workspace works but not Exit and save) wont work. And I am sure, some further issues i will see. Menu looks strange, seperators looks like empty lines in menu commands.

    Issues see with
    - Tool Ähnliches Aktivieren
    - Callout Tool
    - Auto Dimension
    - Elevation Benchmark
    - Measure Angle
    - Grid Axis
    - Eye Dropper
    - Parallel Tool

    Just too many tools do not work it looks ... 

    Promising at the first look, the second look is  disapointing but still better, than i thought but for me no alternative to a native Windows System. 😢

  7. I think there is no difference between VMWare or Native ARM System. Vectorworks run in "compatibility - Mode" on ARM Windows. except in VMWare or parallels it is just slower. From my sight, VMWare seems to play in one league higher than parallels.

    Emulating Software somehow does hurt my hart but if i really look at my Solution:

    1. Money was spent on a very nice and powerfull M3 max (How i love that machine ...)
    2. Running the Emulation thing is a sacrilege but in fact: I can run A Windows system with an startet Vectorworks in 20 Seconds! by just pausing the Virtual machine and saving the state:
    3. Speed and lags are comparable to a Medium Windows System which is 3 Years old. Still i need much less power to work on that system
    4. Additionally the hope, that update of Windows and native ARM Software will even improve the situation

    If i look at the facts in that moment i will not buy a new pc for some time and i think i will practice this "sacrilege" workflow. 

    • Like 1
  8. Hi Marcel
    Thank you very much for responce. So far my experience, that it was able to install VW with an alternative Windows Image (Win 11 ARM). After starting VW Mentioned, that some vlb was not able to load. (Cinerender)

     MaxonRender.png.80e26d6a40c6e64720b631820a288a05.png

    After That VW works quiet smooth and fix in 2D, but in 3D nothing visible. Like you mentioned. Also no wireframe model. 
    After Deactivated the Parallels Display driver, the 3D Shaded view is visible but it is very slow. Also a bigger modell crash.


    Next Test with VM Ware Fusion. Test-Version. I only have two CPU cores. I hope this is because of free Test Version. 
    After Installing Windows 11 with the same iso image i was able to install VW. With VM Ware Fusion it was able to install something like VMWare Tools. This installing Drivers also Display Drivers. After Restart i have a Graphic Adapter Named VMWare SVGA. Then I start VW. It Installation and startup of VW is slower than on parallels. But on Parallels I had 12 CPU Cores and on VWMare Fusion . Only two. After Shut Down the virtual Machine i can set up more cores
     

    It seems to be good enough for testing, Support but not for really working or offering as a Training Computer for Customers. Additionally Cinema 4D do not run at all. But Shades View is OK.

     

     



     

    image.png


    Edit:
    After giving the virtual Machine more than 4GB RAM, it works better 🙂
    But Still generating the 3D Takes more time and the double emulation (Mac Silikon > Windows ARM > Win 11 ARM > Winx86 VW) seems to be incompatible to the VW Render-System.

  9. Hi
    I try to install a Windows Version on Parallels on my m3 for special Support- and Training cases. 
    After all i found out, Parallels 19 needs a Windows 11 ARM Version. And on a Windows ARM Version, the Installer of Vectorworks 2024 will not start. Somebody have experience with that constellation?

     

    Thanks

  10. "C:\\Temp\\Output.csv" would work also
    I would strongly recommend,  always create path strings with the path module. So it is as proof as it can be and this works also cross-platform:
     

    import os
    path = os.path.join('C:', 'Temp', 'Output.csv') 
    
    # or even more propper
    path = os.path.join('C', os.sep, 'Temp', 'Output.csv') 


     

    • Like 2
  11. I would say maybe a rookie error:
     

    #allowed >> produces no errors caching is off
    vs.SetPref(412, True)  # turn off caching
    
    #don't do that >> seems to breaks the vs modul or ignore newer methods
    vs.SetPref(412, False)  # turn off caching
    
    #allowed >> produces no errors caching is on
    #vs.SetPref(412, True)  # turn off caching

     

    • Like 1
  12. Hello

    I have a Vectorscript tool (not Event driven 2024). This tool rund a python module. The tool is working so far.
    code of the tool
     

    PROCEDURE ClickCallback;
    VAR
    	x1, y1 : REAL;
    	path : STRING;
    
    BEGIN
    SetCursor(LgCrossC);
    GetPt(x1, y1);
    PythonExecute('import dev.tool.mod.poly2PIO');
    END;
    
    RUN( ClickCallback );


    the module poly2PIO runs this code:

    import vs
    import os
    #vs.SetPref(412, True) #turn off caching
    
    #vs.Message(str(dir(vs)))
    
    with open(os.path.expanduser('~') +'/file_vst.txt', "w", encoding='utf-8') as f:
    	f.write('\r'.join(dir(vs)))
       
    # error here isOnLine undefined method   
    isOnLine = vs.PtOnLine((0,0), (-10, 0), (10, 0), 0.00001)


    everything and also vs.PtOnLine() is working. If i use that tool.

    But then, if i run run another vso (Event Enabled path object) it seems that the vst does not have the same vs-function anymore as before.
    Also if i use a standard vso (Script Based like the Rolling Stairs) the vs class in my vst do not contains the same methods anymore.

     

    import vs
    #from datetime import datetime
    import json
    import math
    import copy
    #import uuid
    import os
    import base64
    import time
    #import urllib.request
    import code.common.controler as controler
    
    #vs.SetPref(412, False)  # turn off caching
    
    with open(os.path.expanduser('~') +'/file_vso.txt', "w", encoding='utf-8') as f:
    	f.write('\r'.join(dir(vs)))



    The functions in the  vst does not work anymore. Also other vst's have the same issues now. 

    The special thin i do is, that i run a pascal script and call a python after i click in the drawing. For further debug i write a text file with dir(vs) which lists all methods of the vs class.

    If i then compare the two files, i can see, that the dump written from file_vst.txt has much less methods available (left) as the file dumped from the vso?
    Somebody knows if this is a normal limitation or if it is worth for further diving in? 

    I think not many devs wrapps a pascal around a python script so maybe this is a normal limitation that the methods freezed on a specific version or it is just a bug?


    It looks some-like, that methods after 2014 are not included now for my vst. 
    Anybody knows what could going on?



    Here a screenshot from the method list compared with diff Merge
    image.png.6c1137530d3580bfbe74bd1579bbb13f.png

  13. Marionette is a Programming-Tool. In such tools wer are in a place to have the force to produce wonderful artwork or unwanted behaviors (crashes?) and comparative we are mostly alone with our artworks. And thanksfully there are forums like this other people can help for bringing those projects to success.

    I took a look a the Marionette Control-Point and agree,  there is some space for improvement:

    1. Fixing Axis
    I think @Gregi wantet to fix one axis. This is not possible because the position of the control-point  comes from the Mouse not from a value inside the script. This value is just a default value. To change the control point by script itself is theoretically possible to manipulate the Record of the Marionette Node where the position of the point is stored but it would be very hard (Because also the position of the PIO is involved). So this is not a bug it works the way the feature is designed.

    2. Moving 3D Point in Standard View.
    If I am in a standard view (front right etc.). Lets say from right and I move the point in z-Direction, the x value from the point snaps on the working plane and the x-value gets 0. Which can maybe produces issues in the script inside the PlugIn. So working plane should be used or unwanted values have to be intercepted inside the script (which is always the most costly part). So if the script crash because the width of the pio change to 0 it is not a bug in the code of the 3D modification point. It is just an unhandled error. Error can be handled on different places. In shoft:
    OK, I can see, that the reshape behaviour of this modi-point can be improved and i will report this as an enhancement Request.

    3. Position of the 3D Point outside of PIO geometry.
    If the Modification Point is the most outside object in a PlugIn. And not geometry is there, the position of the Point somehow is calculated wrong relatively to the object. So in our test with Extrudes etc. it always works as expected. But If the extrude is smaller than the bbox of the modipoint and the 0-point it somehow Fails.
    I think, this is definitely a bug. I will report.

    4. Position of the 3D Point with layer elevation

    I think this is already known but I try to give it an impact.

    Generally, there are not much additional layers of error-handling between marionette and the Script Engine. I think the more "idiot-proof" something is made the weaker it is. Not 100% the truth (It could be possible to have both). But this is the way I am still pleased even if my script crashes 😁

  14.  OK, the part of the code which I will not paste is the part how you update your certificates by the script on mac computers to make python accept them to communicate over TLS (SSL) (https instead of http).

    caution should be exercised. 

  15. The forum allows me not to paste some code ... I think maybe for security reasons.
     

    Or your testing api request:

    import urllib.request
    import json
    
    
    api_url = "https://jsonplaceholder.typicode.com/todos/1"
    
    result_string = ''
    with urllib.request.urlopen(api_url) as f:
       result =  json.loads(f.read().decode('utf-8'))
    
    
    vs.AlrtDialog(str(result))

     

    An other real example with a http request url, if you can't get https to work

     

    import urllib.request
    import json
    import math
    
    
    #dezimalgrad in minuten und Sekunden umwandeln (copy paste aus dem Netz)
    def deg_to_dms(deg, type='lat'):
    	deg = float(deg)
    	decimals, number = math.modf(deg)
    	
    	d = int(number)
    	m = int(decimals * 60)
    	s = (deg - d - m / 60) * 3600.00
    	compass = {
    		'lat': ('N','S'),
    		'lon': ('E','W')
    	}
    	compass_str = compass[type][0 if d >= 0 else 1]
    	return '{}º{}\'{:.2f}"{}'.format(abs(d), abs(m), abs(s), compass_str)
    
    
    
    
    h = vs.FSActLayer()
    x = 2600000
    y = 1200000
    z = 500
    #Nimmt Position von aktiviertem Hilspunkt, Objekt oder Symbol sonst Bern Sternwarte als Vorgabewert
    if h != vs.Handle(0):
    	x,y,z = vs.GetLocus3D(h)
    
    
    #vs.AlrtDialog(str(vs.GeogCoordToVWN(x, y)))
    vs.AlrtDialog(str(vs.VWCoordToGeog(x, y)))
    
    
    
    xPt, yPt, zPt = vs.PtDialog3D('LV95 Koordikante zu WGS84', x, y, z)
    
    #Abfragestring auf dem Geportal direkt im Internet
    url = "http://geodesy.geo.admin.ch/reframe/lv95towgs84?easting="+str(xPt)+"&northing="+str(yPt)+"&altitude="+str(zPt)+"&format=json"
    
    
    result_string = ''
    with urllib.request.urlopen(url) as f:
       result =  json.loads(f.read().decode('utf-8'))
    
    
    #Antwort vom Geoportal interpretieren und umwandeln in json
    result_string = str(result['easting']) + '\r' + str(result['northing']) + '\r' + str(result['altitude'])+'\r\r'\
    'Grad: '
    
    result_string += '\r'
    result_string += 'Grad Minuten Sekunden: \r' + deg_to_dms(result['easting'], 'lat') +'  ' + deg_to_dms(result['easting'], 'lon')
    
    vs.AlrtDialog(str(result_string))

     

  16. Oh, this is an old code and not very nice one. Without testing:

    1. The vs.GetType should replaced by:

    vs.GetTypeN(res)


    2. The node returns not the Symbol Name. That means the node itself insert the Symbol. In fact it looks, like the output just returns the last inserted symbol. Which means the node should insert the symbols in the number of rows and should do the job but not returning the resulting symbol handles. With that node, you can't use the output useful disconnect symbol node and print debug node.

  17. Hi
    A possible workaround I once used is:
    1. I had a big library document with much of Elements. Importing, reading informations, delete/purge would be time-consuming.
    2. On the library document running a script after every change. The Script dumps the needed informations to a file which contains the metha-data from the library file
    3. Or alternatively dump to a text object inside a symbol (I think does not work with too much data because of text size limitation maybe) and just import that index symbol to read source data
    4. If the process should be automated there could be used a custom "save" command which dumps the data automatically before saving the file

     

    import json
    
    def update_library():
        log_info = []
        log_info_sym = []
        counter_sym = 0
        counter_xg = 0
        listID, numItems = vs.BuildResourceList(16, 0, '')  # Symbols
    
        dumps = {}
        SymbolLibraryDump = None
    
        for i in range(1, numItems + 1):
            counter_sym += 1
            res_name = vs.GetNameFromResourceList(listID, i)
            sym_h = vs.GetResourceFromList(listID, i)
    
            if sym_h != vs.Handle(0):
                t = vs.GetTypeN(sym_h)
                found_cabinet = functions.get_XG_Cabinet_h_in_symbol(sym_h)
    
                if found_cabinet:
                    dump = functions.attach_infos(sym_h, found_cabinet)
                    dumps[res_name] = dump
                    counter_xg += 1
                    log_info_sym.append(f"{res_name} {dump}")
                else:
                    pass
                    # log_info.append('kein Korpusmöbel gefunden')
    
                if 'SymbolBibliothekDump' in res_name:
                    SymbolLibraryDump = sym_h
            else:
                vs.AlrtDialog(str(res_name))
    
        if SymbolLibraryDump:
            vs.DelObject(SymbolLibraryDump)
    
        log_info.append('Daten an Symbole anghängen:')
        log_info.append(f"{counter_sym} Symbole im Dokument-Zubehör")
        log_info.append(f"{counter_xg} Symbole mit KM im Dokument-Zubehör")
        log_info = log_info + log_info_sym
    
        field_value = json.dumps(dumps, indent=1)
        vs.BeginSym('SymbolBibliothekDump' + vs.Date(2, 2))
        vs.CreateText(field_value)
        vs.EndSym()
        log_info.append('Dump Symbol generiert (index zum auslesen aus anderen Dateien)')
    
        log_info = rename_symbols(log_info)
    
        return log_info

     

×
×
  • Create New...