Jump to content

tbexon

Member
  • Posts

    76
  • Joined

  • Last visited

Posts posted by tbexon

  1. Hi All

     

    I'm trying to add a resource selector to a Event enabled, custom Widget enabled PIO, that will allow the user to select a texture. I'm using the kWidgetButtonResourcePopup (107) widget type.

     

    I can insert the ResourcePopup into the OIP fine (SS Below), however when clicked I'm not getting any button ID passed to kObjOnObjectUIButtonHit (35).

     

    image.png.3424f21394a1f5c7e591e34d2de7db8a.png

     

    I added a generic test button to make sure it wasn't something else and that successfully passes the Button ID to the kObjOnObjectUIButtonHit event. Is there possibly a different event type I need to look for? Or is there a setting I need to enable?

     

    I'm aware I need to use vsoButtonGetResource() to handle the Resource browser, which brings me onto my next question, according to https://developer.vectorworks.net/index.php?title=VS:vsoButtonGetResource the "Parameter name is a string that will receive the resource name" however this appears to be a param I pass to the function and, certainly according to the docs atleast, it will only return a bool. How am I meant to extract the Param string?

     

    Relevant code below! Thanks in Advance!

     

    kWidgetButtonResourcePopup = 107
    
    def execute():
        global PIO,localized_True_bool
    
        GetImageButton_ID = 1001
        
        theEvent, eventMessage = None, None
        theEvent, eventMessage = vs.vsoGetEventInfo(theEvent, eventMessage)
        if theEvent == tb.Constants.kObjOnInitXProperties:  # If the event is the initilisation of object propeties
    
            # Enable custom shape pane
            ok = vs.SetObjPropVS(tb.Constants.kObjXPropHasUIOverride, True)  # Enables customisation fo widgets
            ok = vs.SetObjPropVS(tb.Constants.kObjXHasCustomWidgetVisibilities,
                                 True)  # allows PIO to control the widget state in OIP
            ok = vs.SetObjPropVS(tb.Constants.kObjXPropPreference, True)  # Enables preferences menu for PIO
    
            vs.SetPrefInt(tb.Constants.kParametricEnableStateEventing, 1);
            ok = vs.SetObjPropVS(tb.Constants.kObjXPropAcceptStates, True);
    
    
            ok = vs.vsoInsertAllParams()  # Inserts all Parameters into OIP
            bool = vs.vsoAddWidget(GetImageButton_ID,kWidgetButtonResourcePopup,'Select Image')  # Adds Select Image Button
            bool = vs.vsoAppendWidget(tb.widgetTypes.WidgetButton,1234,'Test', 0)
    
    
        elif theEvent == tb.Constants.kObjOnWidgetPrep:  # If event is widget Prep
    
            tb.WidgetGenericPrep()  # Sends message that all widget prep has been completed
    
        elif theEvent == tb.Constants.kObjOnObjectUIButtonHit:
            vs.AlrtDialog(eventMessage)
            if eventMessage == GetImageButton_ID:
                vs.vsoButtonGetResource(GetImageButton_ID, 97, 0, 0)
        elif theEvent == tb.Constants.kObjOnAddState:
          GenericGetStateChange(eventMessage)
        elif theEvent == tb.Constants.kObjXPropPreference:
            MakePropDialog()
        elif theEvent == tb.Constants.kResetEventID:  # If the event is a object reset
            start_unit_index = tb.SetUnitsToMM()  # Gets Current Units, and sets units to MM
            init()
    
            vs.Units(start_unit_index)  # Resets Units
    
            vs.vsoStateClear(PIO.PIHan)

     

  2. Amazing thanks!

     

    Working code if it's of help for anyone:

     

    projectionMode = vs.GetProjection(vs.ActLayer())
        if projectionMode != 6:
            # If the user is NOT in 2D Top/Plan View
            xAngleR, yAngelR, zAngleR, offset = vs.GetView()  # Saves current view for Later
            vs.SetView("0d", "0d", "0d", "0", "0", "0")  # Sets view to top down
            vs.SetPref(tb.PreferenceSelectors.DisableScreenRedraw, True)  # Disables screen redraws temporarily
            
    # ------------- Other Code here ----------------------#
    
    if projectionMode != 6:
      # If user is NOT in Top/Plan, then reset 3d view
      vs.SetView(xAngleR, yAngelR, zAngleR,offset[0], offset[1],offset[2])
      vs.SetPref(tb.PreferenceSelectors.DisableScreenRedraw, False)  # Enables screen redraws

     

  3. HI All

     

    I'm sure I'm missing something obvious, but I've been searching through the Function reference aswell as preference selectors, and I'm struggling to find what I'm looking for.

     

    Basically within a PIO I need to set the view to a specific view, then for a better User Experience I want to return the user to their previous view (Code Below). This works fine if the user is in a 3d view, however if they are in Top/Plan it will always swap to 3d, which whilst not a massive disaster also isn't ideal. 

     

    What i'm looking for is some kind of command where I can check whether the user is in a 3d view or 2d, and then, if in 2D, set the view BACK to 2d once the operation has been completed.

     

    xAngleR, yAngelR, zAngleR, offset = vs.GetView()  # Saves current view for Later
    vs.SetView("0d", "0d", "0d", "0", "0", "0")  # Sets view to top down
    
    vs.SetView(xAngleR, yAngelR, zAngleR,offset[0], offset[1],offset[2])  # Resets View back to previous user view

     

     

    Thanks in Advance!

  4. HI All

     

    I've been bashing my head against this problem for a couple of days now, and struggling to come up with a solution.

     

    I'm trying to create a PIO that draws a line of rectangle extrudes that are rotated by a specific amount, and aligned so that the bottom left corner touches the previous Bottom right. (image showing desired end result)

     

    image.thumb.png.1854c013d544e42204027c65a7fa8e17.png

     

    At the moment it nearly works, however I am having issues with the more objects I insert they start to "drift" and gaps appear. (SS Below)

     

    image.thumb.png.dbcc56dcfd639c51cb29ab9d8e4f520a.png

    I think this is basically because as the rotation of the rectangle increases the total length along the X axis reduces, and I am struggling to find a way to calculate this offset. I've managed to deal with the Y Offset by using vs.GetBBox() to get the Bottom RightY Value and using this as Y value for lining the next object up with the previous. 

     

    However for the X axis this doesn't seem to work as the X bounding box value will default to furthest point on X axis which is the TOP Right point not bottom right.

     

    Is there a way I can easily get the co ordinates of each corner of the rectangle once it's rotated? Or do I need to try and remember how to do Trig and calculate this myself?

     

    I'm also wondering whether the issue is with the X, Y, Z Distance within Set3d Rot? Currently i'm trying to make the rotation centre the bottom left corner, but i'm wondering whether I should be using some other static centre for all of them.

     

    Any help is greatly appreciated! I've been staring at this for so long now I can't see the wood for the trees!

     

    Relevant Code below:

     

    def MakeCurvedScreen():
        """
        Creates a curved screen based on user specified number of panels & rows
        :return:
        """
    
        TileWidth = 1000  # Tile Width (X)
        TileDepth = 95  # Tile Depth (Y)
        TileHeight = 1000  # Tile Height (Z)
        TileQty = 8  # Number of tiles in each Row
        NoOfRows = 1  # Number of Rows
        tileZRot = -2  # Rotation angle for each Tile
    
        tileXoffset = 0  # Amount to offset each tile along X Axis by to create rows
        tileZOffset = 0  # Amount to offset each tile along the Z axis by to create columns
        curTileQty = 0  # Tracks current amoutn of tiles inserted in current row
        curtileZRot = 0  # Tracks current height of row being inserted
        totalTiles = TileQty * NoOfRows  # Total Tiles in screen
        col_index = 0  # Tracks what Column we are currently inserting into
        prevTileYLoc = 0  
        CorrectionX = 0
    
        for EachTile in range(totalTiles):
          # Iterates through all tiles building wall
            if curTileQty == TileQty:
                # If a full row of tiles has been inserted, start new row
                tileZOffset += TileHeight
                curtileZRot += tileZRot
    
                curTileQty = 0
                tileXoffset = 0
                col_index = 0
                prevTileYLoc = 0
    		
            # Creates Tile as extrude, adds a Y offset to account for the rotated tile being lower
            tileH = MakeSingleTile(0 + tileXoffset , 0 + tileZOffset, TileWidth, TileDepth, TileHeight, YOffset=prevTileYLoc)  
            # Rotate Tile
            vs.Set3DRot(tileH, 0, 0, tileZRot * col_index, TileWidth*col_index,(TileDepth*col_index)*-1, 0)  # Rotates Tile
    
    
            (p1X, p1Y), (p2X, p2Y) = vs.GetBBox(tileH)  # Gets previous tiles co ords
    
    
            prevTileYLoc = p2Y  # Gets the Bottom Right corner of current Tile for use with lining up the next tile
            
            tileXoffset += TileWidth  # Increases Overall Row width count by panel width
            curTileQty += 1
            col_index += 1
    
    def MakeSingleTile(startX,startZ,width,depth,height, **kwargs):
        """
        Creates a Single Tile from Rectangle of user specified Width & Depth
        :return: Handle
        """
        vs.BeginXtrd(0,height)
        vs.RectangleN((0,0),(1,0),width,depth)
    
        vs.EndXtrd()
        tileH = vs.LNewObj()
        if 'YOffset' in kwargs:  # If a Y Offset has been specified
            vs.Move3DObj(tileH, startX, kwargs['YOffset'], startZ)
        else:
            vs.Move3DObj(tileH,startX,0,startZ)
        return tileH

     

     

  5. HI All

     

    Apologies if this has been answered somewhere already I'm struggling to find any answers.

     

    I am using vs.NameClass() to create a new class within a PIO. Is there a way to make that Class automatically visible in Viewports AND saved views similar to functionality within the new class dialog (SS below for reference)

     

    image.png.64b864a2999944c19a78ac5ea3776031.png

     

    I'm basically looking for a way to force that class to be visible within all Viewports & Saved views to stop the user having to go through and edit them afterwards.

     

    I'm guessing I could iterate through every single viewport once the class is created and edit the visibility there. But that seems massively time consuming and inefficient. Especially for a large document.

     

    If this is the only option available to me, does anyone know if this approach would also work with Saved Views? I can see a function for creating a new Saved View (vs.SaveSheet()) but nothing to get a list of saved views or edit one.

     

    Thanks in Advance!

  6. So if I'm reading this correctly you want to be able to Run a command in VWX that will export a set of data as a CSV to then import this into your label printer software?

     

    First question is where is the Data coming from? Is the data in an already existing worksheet or do you need to get it yourself? If the latter is the case you have a couple of options:

     

    You can either build a worksheet that collects the data for you or you can get the data yourself using the ForEachObjectInLayer() command to cycle through all the relevant objects and retrieve the data you need. You would then write this data to a worksheet (have a look at these commands). 

     

    You can then export the worksheet to CSV. Below is the code I use to achieve this. It will export the CSV to the specified directory.

     

    def exportWStoCSV(ws, FilePath, **kwargs):
        '''
        subRowNo: specify sub row to extract data from
        HeaderRowNo: States which row the Column Headers are in
        :param ws: string
        :param FilePath: string
        :param kwargs:
        :return:
        '''
        import csv
        try:
            h = ws
            vs.TargetSprdSheet(h)  # Makes ws active
            vs.RecalculateWS(h)  # recalculates the worksheet
        except:
            return False
        if 'subRowNo' in kwargs:
            if 'subRowNo' in kwargs:
                subrowNo = kwargs['subRowNo']
                subRowCount = vs.GetWSSubrowCount(h, subrowNo)  # Counts the total Sub Rows in Row 2
                subRowCountRange = list(range(subRowCount + 1))  # Creates a itertable range for N.o of subRows
                zz = subRowCountRange.pop()  # Removes the last value from list to account for 0 index
    
        number_of_rows_and_cols = list(vs.GetWSRowColumnCount(h))  # Counts total Rows and Columns in Worksheet
        totalColumnsRange = list(range(number_of_rows_and_cols[1]))  # Creates a itertable range for N.o of columns
    
        totalRowRange = list(range(number_of_rows_and_cols[0]))  # Creates a itertable range for N.o of rows
    
        if 'HeaderRowNo' in kwargs:
            headerRow = kwargs['HeaderRowNo']  # States which row the Column Headers are in
        else:
            headerRow = 1  # States which row the Column Headers are in
        headersList = [vs.GetWSCellStringN(h, headerRow, eachColumn + 1) for eachColumn in totalColumnsRange]  # Creates a list with all the Column Headers
        if 'subRowNo' in kwargs:
            list_of_cells = [[vs.GetWSSubrowCellString(h, 2, eachColumn + 1, eachSubRow + 1) for eachColumn in totalColumnsRange]
                             for eachSubRow in subRowCountRange]  # Creates a List containing a list of each row e.g overalllist = [[Row1],[Row2],[Row3]]
        else:
            list_of_cells = [
                [vs.GetWSCellStringN(h, eachRow +1, eachColumn + 1) for eachColumn in totalColumnsRange]
                for eachRow in totalRowRange]  # Creates a List containing a list of each row e.g overalllist = [[Row1],[Row2],[Row3]]
            list_of_cells.pop(0)  # Removes header row
        try:
            with open(FilePath, 'w', newline='', encoding='utf-8') as csvfile:  # opens or Creates CSV Called Loom Data
                writer = csv.writer(csvfile)
                writer.writerow(headersList)  # Writes the Headers to the file.
                for eachList in list_of_cells:
                    writer.writerow(eachList)  # Writes each Row to CSV
            return True
        except Exception as e:
            vs.AlrtDialog("Error Occured, CSV Not Written! Error Message to follow.")
            vs.AlrtDialog(str("Error Msg: {}".format(e)))

     

     

    If you're collecting the data yourself don't necessarily need to write the data to a worksheet you could just build the data into the required format for csvwriter. However I find for a better user experience it's good to show them the data within VWX aswell.

     

    Hope that's helpful!

    • Like 1
  7. I'll be honest I've just gone back over my template, and I've no idea why I'm using kObjXPropPreference...

     

    It's been a couple of years since I made that template. But certainly in terms of functionality it appears to work the same as kObjOnInitXProperties. (though I'm sure there is a difference) maybe @JBenghiat can shed some light).

     

    But basically within that call i'm just building the preferences dialog, and setting default values

    • Like 1
  8. So thanks to the wonderful @VladoI have managed to get this working! There is a bug with developer mode that was causing the crash. Disabling developer mode, so that the script didn't run twice each time solved the crashing issue.

     

    Below is an explanation of my process, and what I understood is happening based on Vlados Explanation to me.

     

    Working with a Event Enabled Plug In Object, use the below template.

     

    When the button in the OIP is clicked, the ButtonClick() function is called. Within this function we call the vs.GetPt() command, passing a function as an arguement (in this case PickPointCallback). 

     

    The way I understand what's happening is: When you run GetPt, it effectively restarts the script, clearing out all your code, and JUST runs whatever code is within the PickPointCallback function. Hence why any variables you may try and call or save won't affect anything outside of the function. To get around this, within the PickPointCallback we can save whatever values we wish to the Value Repository, which will temporarily save them into the documents session.

     

    I am saving 2 Values. Firstly a string containing the Co ordinates the user selected. The second is a bool indicating that the GetPt has been called but not handled. The reason for this is that once the GetPt call has been made the PIO won't automatically reset. We need to manually send it a reset event using vs.ResetObject(objectHandle). The reason i'm using the 'newFixtureBool' is because otherwise the main Init code won't know whether it's running after the UIButton has been pressed, or from some other Reset Event. There are other approaches, you don't necessarily need to use a Bool to track whether the button has been hit or not, it really depends on your specific project.

     

    Hopefully this is of help to someone, if anything is unclear, please do just ask, and I will do my best to help! Once again massive thanks to Vlado for figuring this out, and sending me on the right path! 

     

    def makeOIP():
        global objectHand , BackgrdColourDict, ForeGrdColDict, position_note_rec_name
        ok, objectName, objectHand, recordHand, wallHand = vs.GetCustomObjectInfo()
        theEvent, theEventData = vs.vsoGetEventInfo()  # Gets Object Event info
        
        if theEvent == tb.Constants.kObjOnInitXProperties:  # If the event is the initialisation of the object
          ok = vs.SetObjPropVS(tb.Constants.kObjXPropPreference, True)  # Allows for creation of custom OIP
          ok = vs.SetObjPropVS(tb.Constants.kObjXPropHasUIOverride, True)  # Custom OIP Overrides standard UI
          ok = vs.SetObjPropVS(tb.Constants.kObjXPropPreference,True)  # Enables preferences menu for PIO
          ok = vs.SetObjPropVS(tb.Constants.kObjXHasCustomWidgetVisibilities,True)
    
          vs.vsoInsertAllParams()  # Inserts all Parameters floato OIP
    
          result, scaleWidID = vs.vsoPrmName2WidgetID('','Scale')
          thisDoesNothing = 0
          result = vs.vsoAppendWidget(tb.widgetTypes.WidgetButton, link_pos_button_id,'Get Position Info', thisDoesNothing)
            
        if theEvent == tb.Constants.kObjOnWidgetPrep:
           WidgetPrep()  # Sets Info within the OIP
        
        if theEvent == tb.Constants.kObjXPropPreference:
            defaultVals = {} # Creates blank Dict for default vals
            MakePropertiesDialog()
        
        if theEvent == tb.Constants.kObjOnObjectUIButtonHit:  # If the event is a button being pressed
            if theEventData == link_pos_button_id:  # If the Button Pressed is Link Position Button
                ButtonClickFunction()  # Runs the GetPt Command
                vs.ResetObject(objectHand)  # Resets the Plug In object
        if theEvent == tb.Constants.kResetEventID:  # If Object is reset
            init()  # Creates the Object
            
    makeOIP()

     

    def ButtonClickFunction():
        """
        Prompts the user to select a point on the drawing, and then calls the PickPointCallback function with the
        co ordinates for the user specified location as an arguement 
        :return: 
        """
    
        try:
           vs.GetPt(PickPointCallback)  # Prompts user to select a point on the drawing
        except Exception as e:
            vs.AlrtDialog(str(e))
            h, p = 0,0

     

    def PickPointCallback(pt):
        """
        Callback function used in GetPt call to allow user to select
        :param pt: XY Co ords user selects
        :return:
        """
    
        # Stores the fixture position as a VWX Value string for retrieving later after GetPt callback has been run
        vs.Rpstr_SetValueStr('tb__PositionLoc',str(pt))
        vs.Rpstr_SetValueBool('tb__newFixtureBool',True)

     

    def init():
        """
        Runs whenever object reset event is called
        :return:
        """
    
        NewFixH_bool = vs.Rpstr_GetValueBool('tb__newFixtureBool',False)
        Fix_H = vs.Rpstr_GetValueStr('tb__PositionLoc', False)  # mGets the saved fixture handle
        if NewFixH_bool:  # If the GetPt call has been made, but not handled 
            SetPositionData()  # Gets the saved GetPt data and do whatever you would like with it

     

    • Like 2
  9. Thanks Dom & Pat, I was worried this may be the case.

     

    Thank you for your suggested solution Dom, unfortunately because I'm only looking to get user input when a button is clicked not on script initialisation, the only way I could see to implement this is to rewrite the base code for building the PIO in Vectorscript, and then call multiple python scripts at appropriate points. Given that this Plug-In is over 2000 Lines of Python, I just don't see the work required to implement this as a reasonable option for the functionality gain.  

     

    I'd be curious to see what is stopping this functionality from being implemented within the Python side of Vector script, Python itself as a programming language definitely has tools to support this.  From a personal perspective it certainly would be a big benefit to some of my tools!

  10. Hi All

     

    So I'm trying to add functionality into an already existing Event based PIO that allows the user to click a button in the OIP and choose a Lighting fixture on the drawing, and get some information from it.

     

    The bit I'm struggling with is finding a way to use vs.GetPt() (or any similar user interactive command) within a Python Event based plug in object.

     

    The structure of the Plug In is pretty standard, the main outline of which is below.

     

    def makeOIP():
        global objectHand , BackgrdColourDict, ForeGrdColDict, position_note_rec_name
        ok, objectName, objectHand, recordHand, wallHand = vs.GetCustomObjectInfo()
        theEvent, theEventData = vs.vsoGetEventInfo()  # Gets Object Event info
        
        if theEvent == tb.Constants.kObjOnInitXProperties:  # If the event is the initialisation of the object
          ok = vs.SetObjPropVS(tb.Constants.kObjXPropPreference, True)  # Allows for creation of custom OIP
          ok = vs.SetObjPropVS(tb.Constants.kObjXPropHasUIOverride, True)  # Custom OIP Overrides standard UI
          ok = vs.SetObjPropVS(tb.Constants.kObjXPropPreference,True)  # Enables preferences menu for PIO
          ok = vs.SetObjPropVS(tb.Constants.kObjXHasCustomWidgetVisibilities,True)
    
    
    
          vs.vsoInsertAllParams()  # Inserts all Parameters floato OIP
    
          result, scaleWidID = vs.vsoPrmName2WidgetID('','Scale')
          thisDoesNothing = 0
          result = vs.vsoAppendWidget(tb.widgetTypes.WidgetButton, link_pos_button_id,'Get Position Info', thisDoesNothing)
            
        if theEvent == tb.Constants.kObjOnWidgetPrep:
           WidgetPrep()  # Sets Info within the OIP
        
        if theEvent == tb.Constants.kObjXPropPreference:
            defaultVals = {} # Creates blank Dict for default vals
            MakePropertiesDialog()
        
        if theEvent == tb.Constants.kObjOnObjectUIButtonHit:  # If the event is a button being pressed
            if theEventData == link_pos_button_id:  # If the Button Pressed is Link Position Button
                link_to_hp()  # Runs 
        if theEvent == tb.Constants.kResetEventID:  # If Object is reset
            init()  # Creates the Object

     

     

    When the button is pressed it calls a function, link_to_hp()

     

    def link_to_hp():
        vs.SetObjPropVS(tb.Constants.kObjXHasCustomWidgetVisibilities, False)  # Sets widget custom visibility to false
        try:
           vs.GetPt(PickPointCallback)
        except Exception as e:
            vs.AlrtDialog(str(e))
            h, p = 0,0
    
        Fix_H = vs.Rpstr_GetValueStr(tb.ValueStrings.FixtureHandle_TempValString,False)  # Stores the Fixture handle as a Vectorworks Value String
        vs.Message(str(Fix_H))
    
        vs.SetObjPropVS(tb.Constants.kObjXHasCustomWidgetVisibilities, True)  # Sets widget custom visibility to True
    
    def PickPointCallback(pt):
        vs.Message('X: ', pt[0], 'Y: ', pt[1])
        Fix_H = vs.vstGetPickObject(pt[0],pt[1])
        # Stores the fixture handle as a VWX Value string for retrieving later after GetPt callback has been run
        vs.Rpstr_SetValueStr(tb.ValueStrings.FixtureHandle_TempValString,Fix_H)
    
        vs.SetObjPropVS(tb.Constants.kObjXHasCustomWidgetVisibilities, True)  # Sets the Custom Widget visibulites back to True

     

     

    The main issue I'm having is that whenever I press the button, the GetPt cross hairs appear, I'm able to select a point, but then Vectorworks crashes, with no error message. I understand the main issue is that the Python function GetPt will not block execution, so I need to use the callback function. However I am still getting the same results.

     

    From a fair amount of searching of the forums, I have found several suggested solutions such as @Paolo suggestion in this thread to disable custom widget visibilities whilst vs.GetPt is running, however sadly this does not seem to have any affect.

     

    I've seen suggestions that there cannot be any functions inbetween the GetPt call, purely as a test I've tried adding a vs.GetPt() at the end of the of the file, with some very dodgy logic to allow it only to run after the UIButton has been hit.

    E.g:

    makeOIP()
    if runGetPt:
        vs.GetPt(PickPointCallback)

    Still no improvement, still crashes with no error.

     

    I've tried completely emptying the PickPointCallback, in case it was something inside there, but still no change.

     

    Does anyone have any suggestions as to how to achieve this kind of functionality within a Python Script? Surely people have managed to find a way around this? @Vlado @JBenghiat @twk 

     

    Thank you in advance!

  11. As has been said above a combination of both is always good, however I would personally be aiming to start with Python, and frankly I think you'll end up doing the majority within that language. It's a hugely transferrable skill, it's easy to learn and the amount of resources available on the web for python are huge (stackoverflow will be your go to saver after this place!)

     

    I program 99% of my plugins in Python, and i've not come up against many scenarios where Python has been the limiting factor. That's not to say they aren't there, as has been outlined above they are there. But 90% of what you're going to want to do can be achieved in Python.

  12. Hi Konstantin

     

    Sorry I should have Explained my issue a bit better, when I get a checkbox using the GetRField Command, I then have to compare it to the localized string for True. I do this using the below function:

     

    def check_locallised_bool(objectHandle,objectName,Field):
        localized_True_Bool = vs.EvalStr(vs.Handle(0), "1=1")  # Gets Localised True Bool
        boolraw = vs.GetRField(objectHandle, objectName, Field)  # Gets the Raw Bool result
        if boolraw == localized_True_Bool:  # If raw string value is equal to localized version of True
            localbool = True
        else:  # If raw string value is NOT equal to localized version of True
            localbool = False
        return localbool

     

    At the moment because in 2021, and according to the Developer page EvalStr returns a string so I am doing a string comparison, to compare the Result of the GetRField to the what I have established to being the String value for True in whatever Language the particular VW user is using. 

     

    In 2022 EvalStr has started returning a Boolean rather than a string, meaning that a String comparison will always return False regardless. My question is whether this is an intended change or a bug? E.g Do I now need to change the logic to instead compare a Boolean result?

     

    Cheers

    Tom  

  13. Hello All

     

    Some potential 2022 funkyness. I use the EvalStr function to get the localized string for "True" to then use this to compare to the results from Checkboxes using GetRField. (For more information on the method/reasoning see the below thread where @JBenghiatvery kindly showed me this method in the first place)  

     

    Since migrating my plug ins to VW2022 I have noticed that EvalStr is now returning a boolean not a string, and thus causing all my comparisons to fail. 

    localized_True_Bool = vs.EvalStr(vs.Handle(0), "1=1")  # Gets Localised True Bool
    vs.AlrtDialog(str(type(localized_True_Bool)))

    I have tried the above test script in both 2021 and 2022. in 2021 it returns the Expected results of the String "True", however in 2022 it returns a Boolean of True.

     

    My questions are:

    A) Can anyone else replicate this and get the same results?

    B) Is this working as intended, or a bug?  I can't see anything on the Function Reference suggesting that this has been changed in 2022, however maybe @Vlado or @K.Lalkovskimight be able to shed some light?

     

    Thanks in advance!

  14. Hello All

     

    I'm pretty sure I know the answer to this already... BUT is there anyway BuildResourceListN (or any of the similar BuildResource command) can access a VW drawing of an earlier version? (e.g Active Drawing is in 2022, and target drawing is 2021)

     

    Everytime I try this it just fails to import anything. Which I suppose makes sense, but I was hoping for the sake of cross version plug-in compatibility there may be a solution (other than the obvious convert the target drawing to the required version)?

     

    Thanks in Advance! 

  15. Following on from this, a question about the actual plug in files themselves (VSM,VSO etc).

     

    Should these be backwards compatible with previous VW versions? Or do I need to distribute them in the oldest version I want to support and then when the user first runs the command it will automatically update it to the latest version?

×
×
  • Create New...