No internet connection
  1. Home
  2. How to

Correct use of string arrays in templates

By danielkassulke @danielkassulke
    2023-06-12 00:35:13.449Z

    Hi all,

    I've whipped up a handy little marker script for creating markers. It is a marker preset that drops a marker named "TAKE #", and it works like this (for PT pre-2023.6):

    • Create a marker, e.g. "SCENE 1".
    • For each take within Scene 1, add "TAKE #" marker preset, that will auto-number from 1 onwards, until you add another marker, for example "SCENE 2", where the "TAKE #" preset will automatically reset back to 1 again.
    // Create a new memory location with a specified type and suffix.
    function newMemoryLocation({ type, suffix }) {
      // Press the "Enter" key on the numpad.
      sf.keyboard.press({ keys: "numpad enter" });
    
      // Wait for the New Memory Location dialog to appear.
      const memLocWin = sf.ui.proTools.newMemoryLocationDialog.elementWaitFor().element;
    
      // Get the marker number from the new memory location dialog.
      const markerNumber = parseInt(memLocWin.textFields.whoseValue.contains("Location").first.value.value.replace("Location ", ""), 10);
    
      // Create the marker name using the marker number and the provided suffix.
      const markerName = `${markerNumber}. ${suffix}`;
    
      // Set the new memory location name.
      memLocWin.textFields.allItems[1].elementSetTextFieldWithAreaValue({ value: markerName });
    
      // If the memory location type is a marker, enable the "Marker" radio button.
      if (type === "marker") {
        memLocWin.radioButtons.whoseTitle.is("Marker").first.checkboxSet({ targetValue: "Enable" });
      }
    
      // Click the "OK" button to create the memory location.
      memLocWin.buttons.whoseTitle.is("OK").first.elementClick();
    
      // Wait for the New Memory Location dialog to disappear.
      memLocWin.elementWaitFor({ waitType: "Disappear" });
    }
    
    // Invalidate the Pro Tools UI.
    sf.ui.proTools.invalidate();
    
    // Activate the main Pro Tools window.
    sf.ui.proTools.appActivateMainWindow();
    
    // Ensure the Memory Locations window is open.
    sf.ui.proTools.memoryLocationsEnsureWindow({
      // Define the action to perform inside the Memory Locations window.
      action: () => {
        const markers = sf.ui.proTools.memoryLocationsWindow.tables
          .whoseTitle.is("Memory Locations")
          .first.invalidate()
          .children.whoseRole.is("AXRow")
          .map(l => ({
            number: l.children.whoseRole.is("AXCell").allItems[0].children.whoseRole.is("AXStaticText").first.title.value.replace("Selected. ", ""),
            name: l.children.whoseRole.is("AXCell").allItems[1].children.whoseRole.is("AXStaticText").first.title.value.replace("Selected. ", ""),
            nameElement: l.children.whoseRole.is("AXCell").allItems[1].children.whoseRole.is("AXStaticText").first
          }));
    
        const resetMarkers = markers.filter(marker => ["SCENE", "SONG", "PIECE", "SEGMENT", "PARA", "PAGE", "LEVEL", "LINE", "CHAPTER", "QUESTION", "ANSWER"].some(name => marker.name.includes(name)));
        const lastResetMarkerIndex = resetMarkers.length > 0 ? markers.indexOf(resetMarkers[resetMarkers.length - 1]) : -1;
    
        const takeMarkers = markers.slice(lastResetMarkerIndex + 1).filter(marker => marker.name.includes("TAKE"));
    
        const nextTakeNumber = takeMarkers.length === 0
          ? 1
          : Math.max(...takeMarkers.map(ml => parseInt(ml.name.split("TAKE ")[1] || "0", 10))) + 1;
    
        // Create a new marker with the suffix "TAKE" followed by the next take number.
        newMemoryLocation({ type: "marker", suffix: `TAKE ${nextTakeNumber}` });
      },
      // Restore the original state of the Memory Locations window after executing the action.
      restoreWindowOpenState: true
    });
    

    The script works 100% of the time, but I feel in over my head when trying to create a template to simplify. I've substituted instances of "TAKE" in the script with a string property [event.props.markerName], and this did what I wanted it to. But I also want to substitute the resetMarkers array with a string array property, so that field can be configured by a user. I don't fully know where I've gone wrong, but I've substituted line 50:
    const resetMarkers = markers.filter(marker => ["SCENE", "SONG", "PIECE", "SEGMENT", "PARA", "PAGE", "LEVEL", "LINE", "CHAPTER", "QUESTION", "ANSWER"].some(name => marker.name.includes(name))); with

    const resetMarkers = markers.filter(marker => [event.props.resetTrigger].some(name => marker.name.includes(name)));

    I have the resetTrigger property as a String[] type, and I've populated the default value to list all the strings at line 50 that I want to reset the marker number, but that change has undermined the functionality of the script, and the take numbers no longer reset after any of the resetTrigger markers are left. Any suggestions as to what I might have overlooked?

    Solved in post #2, click to view
    • 2 replies
    1. Hey @danielkassulke, I can see that you've put the resetTrigger prop inside another array. Since you're using the String[] type for that prop on the template side there's no need to do anything else to it since it is already an array.

      Try this:

      const resetMarkers = markers.filter(marker => event.props.resetTrigger.some(name => marker.name.includes(name)));
      
      Reply1 LikeSolution
      1. Ddanielkassulke @danielkassulke
          2023-06-12 04:27:38.136Z

          Ahhh that makes much more sense. Thanks, Raphael. Didn't realise the js notation becomes redundant. Cheers!