Example Scripts
Introduction
A collection of example scripts to customise, improve or use for inspiration.
Scripts
Transfer Materials
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:
- Run the script.
- Select a Shape.
- Hit the Get button.
- Select another Shape(s).
- Hit the Set button.
View Script
// Set the window title
ui.setTitle("Get, Set, Go");
// Create the buttons
var getButton = new ui.Button("Get");
var setButton = new ui.Button("Set");
// Set global variables
var 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 functions
getButton.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 layout
ui.addStretch();
ui.add(getButton);
ui.add(setButton);
ui.addStretch();
// Show the window
ui.show();
ui.addStretch();
// Show the window
ui.show();
Reload Asset
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:
- Run the script.
- Right click on a Google Sheet Asset (or any asset) in the Assets Window and choose
Copy Asset Id
- Paste that into the text field of the script window.
View Script
// Set the window title
ui.setTitle("Reload Asset");
// Create the UI elements
const 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");
const 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.");
const button1 = new ui.Button("Reload");
button1.setToolTip("Manually reload the asset.");
const button2 = new ui.Button("Start");
button2.setToolTip("Start polling the asset.");
const 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 timer
function 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 class
var callbackObj = new Callbacks();
// Make the timer and feed it the callback object
var 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.
const hLayout1 = new ui.HLayout();
hLayout1.add(input1);
hLayout1.add(button1);
const hLayout2 = new ui.HLayout();
hLayout2.add(label2);
hLayout2.add(input2);
const hLayout3 = new ui.HLayout();
hLayout3.add(button2);
hLayout3.add(button3);
const vLayout1 = new ui.VLayout();
vLayout1.add(hLayout1);
vLayout1.add(hLayout2);
vLayout1.add(hLayout3);
ui.add(vLayout1);
// Show the window
ui.show()
Isometric
Create an isometric look based on the SSR30⁰ technique by setting the Rotation, Scale and Skew for Shapes.
To use:
- Run the script.
- Select some Shapes.
- Click the appropriate button.
View Script
// Set the window title
ui.setTitle("Isometric");
// Set the Scale Y value
const rad = 30 * Math.PI / 180.0;
const scaleY = Math.cos(rad);
// Set the button's width/height
const buttonSize = 30;
// Create the buttons
const buttonTop = new ui.Button("Top");
const buttonLeft = new ui.Button("Left");
const buttonRight = new ui.Button("Right");
const buttonReset = new ui.Button("Reset");
// Set the callbacks. This will be run when the relevant button is clicked
buttonTop.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 layout
const 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 window
ui.show();
Array of Words from a Sentence
Take a sentence and convert it into a String Array of words.
To use:
- Run the script.
View Script
let text = "Here are some words that I'd like to split up into an array.";
const splitArray = text.split(" ");
let 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 Pivot
Set a Shape's pivot based on its bounding box.
To use:
- Run the script.
- Select a Shape.
- 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↓ DownloadView Script
// Set the window title
ui.setTitle("Set Pivot");
const buttonSize = 18
function 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 buttons
const buttonTopLeft = makeButton(ui.scriptLocation+"/pivot_assets/pivot_tl.png");
const buttonTop = makeButton(ui.scriptLocation+"/pivot_assets/pivot_tc.png");
const buttonTopRight = makeButton(ui.scriptLocation+"/pivot_assets/pivot_tr.png");
const buttonLeft = makeButton(ui.scriptLocation+"/pivot_assets/pivot_cl.png");
const buttonCentre = makeButton(ui.scriptLocation+"/pivot_assets/pivot_cc.png");
const buttonRight = makeButton(ui.scriptLocation+"/pivot_assets/pivot_cr.png");
const buttonBottomLeft = makeButton(ui.scriptLocation+"/pivot_assets/pivot_bl.png");
const buttonBottom = makeButton(ui.scriptLocation+"/pivot_assets/pivot_bc.png");
const buttonBottomRight = makeButton(ui.scriptLocation+"/pivot_assets/pivot_br.png");
// Build the required transform data
function 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 clicked
buttonLeft.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 layout
const 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()
const 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()
const 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()
const vLayout = new ui.VLayout();
vLayout.setSpaceBetween(2);
vLayout.add(hLayout1);
vLayout.add(hLayout2);
vLayout.add(hLayout3);
ui.add(vLayout);
// Show the window
ui.show()
OpenWeather API
Query the OpenWeather API to get a location's current temperature.
To use:
- Replace the
YOUR_API_KEY
part of the script with your own from https://openweathermap.org/api. - Create a Text Shape.
- Connect a String Generator (leave Generator as Value (default)).
- Run the script.
- 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 coordinates
const 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 dropdown
const location = new ui.DropDown();
// Create a menu item for each key (city) in the locations dictionary
Object.keys(locations).forEach((item) => location.addEntry(item));
// Set API key
const apikey = 'YOUR_API_KEY';
const client = new api.WebClient('https://api.openweathermap.org');
// Update the temperature when the dropdown changes
location.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 UI
ui.add(location);
ui.show();
Loop Animation Curves
Set the Loop Before or Loop After options for an Animation Curve.
To use:
- Create a Shape.
- Add keyframes to
position.x
. - Either select the
position
attribute or a keyframe. - Run the relevant script depending on selection.
View Scripts
// From a selected Attribute.
const 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.
const 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'.");
}
}