コンテンツにスキップ

スクリプト例

A collection of example scripts to customise, improve or use for inspiration.

This script copies the Fill Color, Stroke Color and Stroke Width of a Shape and then applies them to a selection of other Shapes.

To use:

  1. Run the script.
  2. Select a Shape.
  3. Hit the Get button.
  4. Select another Shape(s).
  5. Hit the Set button.

View Script

// Set the window titleui.setTitle("Get, Set, Go");// Create the buttonsvar getButton = new ui.Button("Get");var setButton = new ui.Button("Set");// Set global variablesvar fillEnabled = true;var fillColor = {"a":255,"b":50,"g":50,"r":50};var strokeEnabled = true;var strokeColor = {"a":255,"b":50,"g":50,"r":50};var strokeWidth = 1;// Set button functionsgetButton.onClick = function () { var sel = api.getSelection(); if (api.hasStroke(sel[0])) { strokeEnabled = true; strokeColor = api.get(sel[0], "stroke.strokeColor"); strokeWidth = api.get(sel[0], "stroke.width"); } else { strokeEnabled = false; } if (api.hasFill(sel[0])) { fillEnabled = true; fillColor = api.get(sel[0], "material.materialColor"); } else { fillEnabled = false; } console.log(fillEnabled);};setButton.onClick = function () { var sel = api.getSelection(); for (let layerId of sel) { if (strokeEnabled == true) { api.setStroke(layerId,true); api.set(layerId, {"stroke.strokeColor": strokeColor, "stroke.width": strokeWidth}); } else { api.setStroke(layerId,false); } if (fillEnabled == true) { api.setFill(layerId,true); api.set(layerId, {"material.materialColor": fillColor}); } else { api.setFill(layerId,false); } }};// Create the layoutui.addStretch();ui.add(getButton);ui.add(setButton);ui.addStretch();// Show the windowui.show();ui.addStretch();// Show the windowui.show();

This Script can be used as a simple shortcut to reload an asset either manually or via a timer to ‘poll’ an asset every [x] seconds. This was built with a Google Sheet in mind where the data may be regularly changing but can be used for anything really.

To use:

  1. Run the script.
  2. Right click on a Google Sheet Asset (or any asset) in the Assets Window and choose Copy Asset Id
  3. Paste that into the text field of the script window.

View Script

// Set the window titleui.setTitle("Reload Asset");// Create the UI elementsvar input1 = new ui.LineEdit();input1.setToolTip("Right click on an asset in the Assets Window, choose 'Copy Asset Id' then paste into here.");input1.setPlaceholder("Enter an Asset Id. e.g. asset#2");var label2 = new ui.Label("Interval (secs)");var input2 = new ui.NumericField(10);input2.setToolTip("Enter an interval (in seconds) for how often to reload the asset.");var button1 = new ui.Button("Reload");button1.setToolTip("Manually reload the asset.");var button2 = new ui.Button("Start");button2.setToolTip("Start polling the asset.");var button3 = new ui.Button("Stop");button3.setToolTip("Stop polling the asset.");button3.setEnabled(false);var interval = input2.getValue();var seconds = interval * 1000// Define a callback class to be used by the timerfunction Callbacks() { // This callback will be called whenever the timer times out this.onTimeout = function () { const asset = input1.getText(); api.reloadAsset(asset); console.log("Asset Reloaded"); }}// Create the callback classvar callbackObj = new Callbacks();// Make the timer and feed it the callback objectvar timer = new api.Timer(callbackObj);timer.setRepeating(true);timer.setInterval(seconds);// Set the callback functions. These will be run when the buttons are clicked.button1.onClick = function () { const asset = input1.getText(); api.reloadAsset(asset);}button2.onClick = function () { button3.setEnabled(true); button2.setEnabled(false); timer.start(); console.log("Polling Started");}button3.onClick = function () { button3.setEnabled(false); button2.setEnabled(true); timer.stop(); console.log("Polling Stopped");}// Create the UI layout.var hLayout1 = new ui.HLayout();hLayout1.add(input1);hLayout1.add(button1);var hLayout2 = new ui.HLayout();hLayout2.add(label2);hLayout2.add(input2);var hLayout3 = new ui.HLayout();hLayout3.add(button2);hLayout3.add(button3);var vLayout1 = new ui.VLayout();vLayout1.add(hLayout1);vLayout1.add(hLayout2);vLayout1.add(hLayout3);ui.add(vLayout1);// Show the windowui.show()

Create an isometric look based on the SSR30⁰ technique by setting the Rotation, Scale and Skew for Shapes.

To use:

  1. Run the script.
  2. Select some Shapes.
  3. Click the appropriate button.

View Script

// Set the window titleui.setTitle("Isometric");// Set the Scale Y valuevar rad = 30 * Math.PI / 180.0;var scaleY = Math.cos(rad);// Set the button's width/heightvar buttonSize = 30;// Create the buttonsvar buttonTop = new ui.Button("Top");var buttonLeft = new ui.Button("Left");var buttonRight = new ui.Button("Right");var buttonReset = new ui.Button("Reset");// Set the callbacks. This will be run when the relevant button is clickedbuttonTop.onClick = function () { const sel = api.getSelection(); for (let layerId of sel) { api.set(layerId, {"rotation": 30, "scale.y": scaleY, "skew.x": -0.5}); console.log('Selected Shapes set to Top.'); }};buttonLeft.onClick = function () { const sel = api.getSelection(); for (let layerId of sel) { api.set(layerId, {"rotation": -30, "scale.y": scaleY, "skew.x": -0.5}); console.log('Selected Shapes set to Left.'); }};buttonRight.onClick = function () { const sel = api.getSelection(); for (let layerId of sel) { api.set(layerId, {"rotation": 30, "scale.y": scaleY, "skew.x": 0.5}); console.log('Selected Shapes set to Right.'); }};buttonReset.onClick = function () { const sel = api.getSelection(); for (let layerId of sel) { api.set(layerId, {"rotation": 0, "scale.y": 1, "skew.x": 0}); console.log('Selected Shapes reset.'); }};// Create the layoutvar hLayout1 = new ui.HLayout();hLayout1.addStretch();hLayout1.add(buttonLeft);hLayout1.add(buttonTop);hLayout1.add(buttonRight);hLayout1.add(buttonReset);hLayout1.addStretch();ui.add(hLayout1);// Show the windowui.show();

Take a sentence and convert it into a String Array of words.

To use:

  1. Run the script.

View Script

var text = "Here are some words that I'd like to split up into an array.";var splitArray = text.split(" ");var arrayLayerId = api.create("stringArray", "String Array");api.removeArrayIndex(arrayLayerId, "array.0");for (let t of splitArray) { let index = api.addArrayIndex(arrayLayerId, "array"); let obj = {}; obj["array."+index] = t api.set(arrayLayerId, obj);}

Set a Shape’s pivot based on its bounding box.

To use:

  1. Run the script.
  2. Select a Shape.
  3. Click a button to set the Shape’s pivot.

This script uses image assets to build the UI. Download the files below and see the notes here on using assets in scripts.

Set Pivot icons↓ Download

View Script

// Set the window titleui.setTitle("Set Pivot");var buttonSize = 18function makeButton(path) { const button = new ui.ImageButton(path); button.setImageSize(buttonSize,buttonSize); button.setSize(buttonSize,buttonSize); button.setDrawStroke(false); return button;}function getFirstSelected() { var sel = api.getSelection(); if (sel.length > 0) { return sel[0]; } return null}// Create the buttonsvar buttonTopLeft = makeButton(ui.scriptLocation+"/pivot_assets/pivot_tl.png");var buttonTop = makeButton(ui.scriptLocation+"/pivot_assets/pivot_tc.png");var buttonTopRight = makeButton(ui.scriptLocation+"/pivot_assets/pivot_tr.png");var buttonLeft = makeButton(ui.scriptLocation+"/pivot_assets/pivot_cl.png");var buttonCentre = makeButton(ui.scriptLocation+"/pivot_assets/pivot_cc.png");var buttonRight = makeButton(ui.scriptLocation+"/pivot_assets/pivot_cr.png");var buttonBottomLeft = makeButton(ui.scriptLocation+"/pivot_assets/pivot_bl.png");var buttonBottom = makeButton(ui.scriptLocation+"/pivot_assets/pivot_bc.png");var buttonBottomRight = makeButton(ui.scriptLocation+"/pivot_assets/pivot_br.png");// Build the required transform datafunction getData(layer) { var bbox = api.getBoundingBox(layer, true); return { offsetX: bbox.width / 2, offsetY: bbox.height / 2, posX: api.get(layer, "position.x"), posY: api.get(layer, "position.y"), pivotX: api.get(layer, "pivot.x"), pivotY: api.get(layer, "pivot.y"), rot: api.get(layer, "rotation"), }}// Set the callbacks - these will be run when the relevant button is clickedbuttonLeft.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.x": data.offsetX * -1, "position.x": data.posX - data.offsetX - data.pivotX, "pivot.y": 0, "position.y": data.posY - data.pivotY}); console.log('Pivot set to left edge.');}buttonRight.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.x": data.offsetX, "position.x": data.posX + data.offsetX - data.pivotX, "pivot.y": 0, "position.y": data.posY - data.pivotY}); console.log('Pivot set to right edge.');}buttonCentre.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.x": 0, "position.x": data.posX - data.pivotX, "pivot.y": 0, "position.y": data.posY - data.pivotY}); console.log('Pivot set to centre.');}buttonTop.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.y": data.offsetY, "position.y": data.posY + data.offsetY - data.pivotY, "pivot.x": 0, "position.x": data.posX - data.pivotX}); console.log('Pivot set to top edge.');}buttonBottom.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.y": data.offsetY * -1, "position.y": data.posY - data.offsetY - data.pivotY, "pivot.x": 0, "position.x": data.posX - data.pivotX}); console.log('Pivot set to bottom edge.');}buttonBottomLeft.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.y": data.offsetY * -1, "position.y": data.posY - data.offsetY - data.pivotY, "pivot.x": data.offsetX * -1, "position.x": data.posX - data.offsetX - data.pivotX}); console.log('Pivot set to bottom left corner.');}buttonBottomRight.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.y": data.offsetY * -1, "position.y": data.posY - data.offsetY - data.pivotY, "pivot.x": data.offsetX, "position.x": data.posX + data.offsetX - data.pivotX}); console.log('Pivot set to bottom right corner.');}buttonTopLeft.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.y": data.offsetY, "position.y": data.posY + data.offsetY - data.pivotY, "pivot.x": data.offsetX * -1, "position.x": data.posX - data.offsetX - data.pivotX}); console.log('Pivot set to top left corner.');}buttonTopRight.onClick = function () { const layer = getFirstSelected(); if (!layer) { return; } const data = getData(layer); api.set(layer, {"pivot.y": data.offsetY, "position.y": data.posY + data.offsetY - data.pivotY, "pivot.x": data.offsetX, "position.x": data.posX + data.offsetX - data.pivotX}); console.log('Pivot set to top right corner.');}// Create the layoutvar hLayout1 = new ui.HLayout();hLayout1.setSpaceBetween(2);hLayout1.setMargins(0,0,0,0);hLayout1.addStretch()hLayout1.add(buttonTopLeft);hLayout1.add(buttonTop);hLayout1.add(buttonTopRight);hLayout1.addStretch()var hLayout2 = new ui.HLayout();hLayout2.setSpaceBetween(2);hLayout2.setMargins(0,0,0,0);hLayout2.addStretch()hLayout2.add(buttonLeft);hLayout2.add(buttonCentre);hLayout2.add(buttonRight);hLayout2.addStretch()var hLayout3 = new ui.HLayout();hLayout3.setSpaceBetween(2);hLayout3.setMargins(0,0,0,0);hLayout3.addStretch()hLayout3.add(buttonBottomLeft);hLayout3.add(buttonBottom);hLayout3.add(buttonBottomRight);hLayout3.addStretch()var vLayout = new ui.VLayout();vLayout.setSpaceBetween(2);vLayout.add(hLayout1);vLayout.add(hLayout2);vLayout.add(hLayout3);ui.add(vLayout);// Show the windowui.show()

Query the OpenWeather API to get a location’s current temperature.

To use:

  1. Replace the YOUR_API_KEY part of the script with your own from https://openweathermap.org/api.
  2. Create a Text Shape.
  3. Connect a String Generator (leave Generator as Value (default)).
  4. Run the script.
  5. Choose a location from the drop down.

View Script

// Requires a scene with a Text Shape and a String Generator (stringGenerator#1)ui.setTitle("OpenWeather API");// Create a dictionary of locations with lat/lon coordinatesvar locations = { "Manchester": { lat: 53.4808, lon: -2.2426 }, "London": { lat: 51.5072, lon: -0.1276 }, "Sheffield": { lat: 53.3811, lon: -1.4701 }, "Delhi": { lat: 28.7041, lon: 77.1025 }, "Anchorage": { lat: 61.2176, lon: -149.8997 }, "Vancouver": { lat: 49.2827, lon: -123.1207 }};// Create a dropdownvar location = new ui.DropDown();// Create a menu item for each key (city) in the locations dictionaryObject.keys(locations).forEach((item) => location.addEntry(item));// Set API keyvar apikey = 'YOUR_API_KEY';var client = new api.WebClient('https://api.openweathermap.org');// Update the temperature when the dropdown changeslocation.onValueChanged = function () { // Save the dropdown selection const locationChoice = locations[location.getText()]; // Match the dropdown selection and set the associated lat/lon if (locationChoice) { lat = locationChoice.lat; lon = locationChoice.lon; } // Send the Get Request... client.get('/data/2.5/weather?lat=' + lat + '&lon=' + lon + '&units=metric&appid=' + apikey); // Check it succeeded. if (client.status() == 200) { const obj = JSON.parse(client.body()); // Extract the temp let temp = obj.main.temp; // Set the Value String Generator's Number attribute api.set("stringGenerator#1", {"generator.number": temp}); } else { console.log('OpenWeather returned an error status: ' + client.status()); }}// Build the UIui.add(location);ui.show();

Set the Loop Before or Loop After options for an Animation Curve.

To use:

  1. Create a Shape.
  2. Add keyframes to position.x.
  3. Either select the position attribute or a keyframe.
  4. Run the relevant script depending on selection.

View Scripts

// From a selected Attribute.var selAttrs = api.getSelectedAttributes();if (selAttrs.length > 0) { const inConn = api.getInConnection(selAttrs[0][0], selAttrs[0][1]); let animCurveId = inConn.split('.')[0]; // 0: Constant // 1: Loop // 2: Loop with Offset // 4: Oscillate // 5: Zero api.set(animCurveId, {"postInfinity": 1, "preInfinity": 1}); console.info("'Loop Before' and 'Loop After' set to 'Looping'.");}
// From a selected Keyframe.var selKeys = api.getSelectedKeyframeIds();if (selKeys.length > 0) { const outConns = api.getOutConnections(selKeys[0], "id"); if (outConns.length > 0) { let animCurveId = outConns[0].split('.')[0]; // 0: Constant // 1: Loop // 2: Loop with Offset // 4: Oscillate // 5: Zero api.set(animCurveId, {"postInfinity": 1, "preInfinity": 1}); console.info("'Loop Before' and 'Loop After' set to 'Looping'."); }}

Create a Layout Group containing the individual letters of a string connected to a Value Behaviour and Falloff.

To use:

  1. Open/run the script.
  2. Enter a string.
  3. Select a variable font.
  4. Set the font size.

Note that this script is set up to connect the to the font’s first axis (fontAxes.0). The Value Behaviour that’s created can be used to adjust the affect of the Falloff on each of the Text Shapes – these values will be unique to each font.

View Script

// Set the window titleui.setTitle("Variable Font with Falloff");// Create the UI elementsvar createButton = new ui.Button("Create");var textInput = new ui.LineEdit();textInput.setPlaceholder("Enter Text");var fontSizeInput = new ui.NumericField(120);textInput.setPlaceholder("Enter Text");var fontDropDown = new ui.DropDown();fontDropDown.populateFontFamilies();// When the button is clicked...createButton.onClick = function () { var textIds = []; var splitString = []; var spacePositions = []; // Function to create the Text function createText(item) { var textId = api.create("textShape", "Letter - " + item); textIds.push(textId); var fontChoice = fontDropDown.getText(); api.set(textId, { "text": item, "verticalAlignment": 3, // Set the Text's Vertical Alignment to Baseline. "verticalLayoutAlignment": 3, "font.font": fontChoice, // "font.style": "Condensed Extrabold", "material.materialColor": "#000000" }); api.parent(textId, layoutId); api.connect(valueVarId, "id", textId, "fontAxes.0"); } // Function to split the Text function getString(string) { splitString = Array.from(string).reverse(); } // Function to split the Text and track spaces function getString(string) { // Reset arrays splitString = []; spacePositions = []; // Iterate through the string Array.from(string).forEach((char, index) => { if (char === ' ') { // Track the position of the space spacePositions.push(index); } else { // Add non-space characters to splitString splitString.push(char); } }); // Reverse the resulting splitString splitString.reverse(); } // Create the Layout var layoutId = api.create("layoutGroup"); api.disconnectInput(layoutId, "maximumSize"); api.set(layoutId, { "spacing": 3, "maximumSize": [1920, 100] }); // Create the Value and Falloff var valueVarId = api.create("value", "Value - Variable"); api.set(valueVarId, { "value": 100 }); var falloffId = api.create("falloff"); api.connect(falloffId, "id", valueVarId, "falloffs"); getString(textInput.getText()); splitString.forEach(createText); // Add Spacer and position it where the 'space' was spacePositions.forEach((spacePos, spacerCount) => { var spacerId = api.create("spacerItem"); api.set(spacerId, { "useFixedSize": true, "fixedSize.x": fontSizeInput.getValue() * .24 }); // Adjust position for spacers already added var adjustedIndex = splitString.length - spacePos + spacerCount; // Place the spacer correctly in the layout api.reorder(spacerId, textIds[adjustedIndex]); });}// Add the elements to the UIui.add(textInput);ui.add(fontDropDown);ui.add(fontSizeInput);ui.add(createButton);// Show the windowui.show();

A simple example which uses a dictionary of data to create and set Shapes in Cavalry. The commented example at the top is an example of how a dictionary can be imported from an external file.

View Script

/* Example of importing a dictionary from an external file ...// Contents of shapeDictionary.jsfunction shapeList() { return {"shape1": { "posX": 40, "posY": 30 },"shape2": { "posX": -200, "posY": 100 },"shape3": { "posX": 300, "posY": -100 },"shape4": { "posX": 0, "posY": 200 }};}api.load(ui.scriptLocation+"/shapeDictionary.js"); // Load the dictionary of shapeslet shapePositions = shapeList(); // Add the dictionary from shapeDictionary.js to a variable*/// Example datalet shapeData = { "shape1": { "posX": 40, "posY": 30, "radius": 50 }, "shape2": { "posX": -300, "posY": 100, "radius": 150 }, "shape3": { "posX": 300, "posY": -200, "radius": 100 }, "shape4": { "posX": 0, "posY": 200, "radius": 75 }}Object.keys(shapeData).forEach(shapeName => { // Loop through each shape within the dictionary const extractData = shapeData[shapeName]; const posX = extractData.posX; // Extract the 'posX' value from the dictionary. const posY = extractData.posY; // Extract the 'posY' value from the dictionary. const radius = extractData.radius; // Extract the 'radius' value from the dictionary. const ellipseId = api.primitive("ellipse", shapeName); // Create an ellipse api.set(ellipseId, { "position.x": posX, "position.y": posY, "generator.radius": [radius, radius]}); // Set the ellipse's attributes.});