Jump to content

tbexon

Member
  • Posts

    83
  • Joined

  • Last visited

Reputation

21 Great

Personal Information

  • Homepage
    https://www.tb-lx.com/prod-lx-plugins/
  • Location
    United Kingdom

Recent Profile Visitors

2,019 profile views
  1. It's definetely a dark mode problem though. I swapped to Light Mode and it worked straight away
  2. Ah do you know thats probably the issue! Do you know what teh naming convention for Darkmode is? By the looks of things I think I need to add "_dark" at the end. But I wonder what do I need to do for the @2x shoudl it be "_dark@2x.png"? I did just quickly manually try copying the images and renaming them to: ProdLXToolSetLogo_dark.png ProdLXToolSetLogo_dark@2x.png But I still get the same not displaying the image problem. I tried selecting both the "normal" image and the Dark image
  3. Hi All I'm having some problems trying to add an image to a ToolSet when editing a workspace. I don't get any errors when assigning the image, but I always get the Missing image Cross instead of the actual image. (SS for reference below) I don't think it's a code related issue as I get the same issues when trying to manually add an image within the Edit Workspace Dialog. Having read this thread I believe my issue is probably related to the DPI of the image. I am 99% sure that the DPI is set to 72DPI, i've tried multiple images all with the same results. As noted in the docs I am using 2 images one with a resolution of 26x20 @72 DPI and a second image with the Filename ending @2x.png at 52x40 @72 DPI. I don't get any errors when I manually import the images (or via code) but I just always seem to get the missing image file icon... I've attached the Icons for reference Any help would be greatly appreciated, been banging my head against this for a day now! I'm sure it's something really basic i'm doing wrong!
  4. So I use GitHub Co Pilot within the PyCharm IDE for writing Python based plugins. It’s definitely helpful and worth having, but as others have said it’s more for autocompletion of this rather than creating an entire plug-in on its own. The documentation available to it, just isn’t enough for it to understand what it’s trying to do. I’ve had multiple instances of copilot making up commands out of thin air that look right, but are in fact completely fictitious. A very handy tool if you already know what the vectorscript should be doing, but it’s certainly as it stands, I don’t see how I will ever be able to write plugins successfully on its own.
  5. Thanks Scott! that's solved the Data Vis issue, but the symbols still aren't aligning properly. I re inserted the Equipment summary from scratch in case it was a refresh issue. (Now on 2024 Update 5)
  6. Hi @Scott C. Parker 2024 Update 1 File attached! Data Vis Test.vwx
  7. Hi @Scott C. Parker Just to piggy back onto this thread. I'm struggling to recreate this. I have the data vis setup the same as in the above file, pointing to the Light Info Record. I can apply the Data Vis to the fixtures and to the old Instrument Summary object fine, but for some reason they are not applying to a Equipment Summary object. Any suggestions where I'm going wrong? Also for the sake of my OCD, is there an option to align all the symbols along a central line instead of left aligned?
  8. 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). 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)
  9. 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
  10. 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!
  11. 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) 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) 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
  12. Thanks Pat! That was exactly what I was looking for! Absolute hero!
  13. 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) 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!
  14. 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!
  15. I’m on site today, but I’ll try and check over the weekend when I’m back at my PC!
×
×
  • Create New...