Scripting API
Runtime-Scripting fuer Tabellen, Scenegraph-Motion, Roboter und UI-Overlays
Uebersicht
confBuild-Skripte laufen direkt im aktiven Editor. Sie koennen Tabellendaten lesen und schreiben, THREE.js-Objekte direkt manipulieren, wiederverwendbare Szenenanimationen anlegen, URDF-Roboter steuern und eigene Oberflaechen ueber dem Editor einblenden.

Tabellenlogik
Verwenden Sie ActiveWorkbook, um Parameter zu lesen, Formeln zu schreiben, ueber Tabellen zu iterieren und gezielte Modell-Rebuilds auszulösen.
Direkte Scenegraph-Steuerung
Mit API.getSceneObject(), API.updateSceneObject() und API.renderScene() aendern Sie die Szene live, ohne das Spreadsheet-Modell neu zu berechnen.
Animationen und Motion
Erstellen Sie benannte Animationen, scrubben Sie deren Fortschritt oder treiben Sie Maschinen und URDF-Roboter direkt aus JavaScript an.
Eigene UI und Debugging
Mounten Sie HTML-, jQuery-UI- oder React-Panels im Editor und lesen Sie Logs sowie Laufzeitfehler direkt aus der Script-API aus.
Schnellstart
Die Runtime ist um drei zentrale Einstiegspunkte organisiert.
ActiveWorkbook
Tabellen lesen, schreiben, Bereiche abfragen und Hilfsfunktionen fuer SheetsAPI
UI-Updates, Scenegraph-Helfer, Animationen, Roboter, Script-UI und Debuggingscene
Szenenbezogene Helfer wie das Erstellen und Aktualisieren von ConnectorsRefresh-Regeln
- Rufen Sie
await API.updateUI()auf, nachdem Sie Tabellenzellen mitActiveWorkbookgeaendert haben. - Rufen Sie
API.renderScene()auf, wenn Sie nur den Live-Scenegraph angepasst haben und keinen Spreadsheet-Rebuild ausloesen. - Zelladressen sind 0-basiert:
{ sheet: 0, row: 0, col: 0 }ist die erste Zelle. - Verwenden Sie fuer Strings am besten doppelte Anfuehrungszeichen.
Minimales Beispiel
async function projectLoaded(project) {
const width = await ActiveWorkbook.getCellSerialized({ sheet: 0, row: 0, col: 1 });
console.log("Projekt geladen:", project?.name, "aktuelle Breite:", width);
await ActiveWorkbook.setCellContents({ sheet: 0, row: 4, col: 1 }, "Bereit");
await API.updateUI();
}
Spreadsheet-Operationen
Verwenden Sie ActiveWorkbook fuer jede zellbasierte Projektlogik.

ActiveWorkbook.getCellSerialized(address)
Aktuellen serialisierten Zellwert lesenActiveWorkbook.getCellFormula(address)
Zellenformel lesenActiveWorkbook.setCellContents(address, value)
Wert oder Formel in eine Zelle schreibenActiveWorkbook.getRangeValues(range)
Einen Zellbereich auslesenActiveWorkbook.getRangeFormulas(range)
Formeln eines Bereichs auslesenActiveWorkbook.getSheetDimensions(sheetId)
Zeilen- und Spaltenanzahl eines Sheets zurueckgebenActiveWorkbook.simpleCellAddressFromString("B5", 0)
Eine Tabellenadresse in ein 0-basiertes Adressobjekt umwandelnActiveWorkbook.simpleCellAddressToString(address, 0)
Ein Adressobjekt wieder in Tabellen-Notation umwandelnBeispiel: Lesen, verarbeiten, schreiben
async function processRows() {
const dims = await ActiveWorkbook.getSheetDimensions(0);
for (let row = 1; row < dims.rows; row++) {
const input = await ActiveWorkbook.getCellSerialized({ sheet: 0, row, col: 0 });
if (!input) {
continue;
}
const result = Number(input) * 2;
await ActiveWorkbook.setCellContents({ sheet: 0, row, col: 1 }, result);
}
await API.updateUI();
}
Live-Scenegraph-Helfer
Verwenden Sie die Runtime-API, wenn Sie sofortige Transform-, Sichtbarkeits- oder Metadaten-Aenderungen benoetigen, ohne Geometrie aus dem Spreadsheet neu zu erzeugen.
API.getSelectedSceneObject()
Das aktuell selektierte THREE.js-Objekt zurueckgebenAPI.getSceneObject(target)
Ein Objekt ueber outputid, Szenenpfad, Namen oder Objektreferenz aufloesenAPI.getSceneObjectState(target)
Einen einfachen Snapshot von Position, Rotation, Scale, Sichtbarkeit und Parent-Info lesenAPI.updateSceneObject(target, updates)
Absolute oder relative Position, Rotation, Scale, Sichtbarkeit, Name oder userData aendernAPI.renderScene(force?)
Den Viewport nach direkten Scenegraph-Aenderungen neu rendernUnterstuetzte Felder fuer updateSceneObject()
Sie koennen position, translate, rotation, rotate, scale, scaleBy, visible, name, userData, angleUnit und render uebergeben.
Beispiel: Selektiertes Teil verschieben
async function nudgeSelection() {
const selected = API.getSelectedSceneObject();
const target =
selected?.userData?.outputid ||
selected?.userData?.path ||
selected?.name;
if (!target) {
console.warn("Kein stabiler Szenen-Target gefunden");
return;
}
await API.updateSceneObject(target, {
translate: { x: 25, z: 10 },
rotate: { z: 15 },
angleUnit: "degrees",
userData: { lastAction: "nudgeSelection" }
});
API.renderScene();
}
Szenenanimationen
Szenenanimationen laufen direkt auf dem Live-THREE.js-Scenegraph. Sie eignen sich fuer Maschinenbewegungen, Oeffnen-Schliessen-Verhalten, Verfahrwege und wiederkehrende visuelle Zustände.
API.animate(target, config)
Eine Animation direkt aus Target und Konfiguration erzeugenAPI.setAnimation(id, config)
Eine benannte Animation erstellen oder ersetzenAPI.playAnimation(id?, restart?)
Eine Animation oder alle Animationen abspielenAPI.pauseAnimation(id?)
Eine Animation oder alle Animationen pausierenAPI.stopAnimation(id?, restore?)
Die Bewegung stoppen und optional die urspruengliche Transform-Basis wiederherstellenAPI.setAnimationProgress(id, progress)
Den Fortschritt zwischen 0 und 1 setzenAPI.setAnimationValue(id, value)
Direkt zu einem konkreten Wert zwischen from und to springenAPI.getAnimation(id)
Status, Richtung, Dauer und Fortschritt einer Animation lesenAPI.listAnimations(id?)
Alle Animationen oder eine passende Gruppe auflistenReferenz fuer die Animations-Konfiguration
Verwenden Sie property als "position", "rotation" oder "scale". Die Bewegungsachse definieren Sie mit axis. Dazu kommen from, to, durationMs, optional delayMs, der Loop-Modus "once", "repeat" oder "pingpong" und Easing wie "linear", "easeOutQuad" oder "easeInOutCubic".
Tipp: Verwenden Sie einen stabilen Target-Identifier. Bevorzugen Sie outputid, dann Szenenpfad, dann Objektnamen.
Beispiel: Hub eines Pneumatikzylinders
async function ONLOADED() {
const selected = API.getSelectedSceneObject();
const target =
selected?.userData?.outputid ||
selected?.userData?.path ||
selected?.name;
if (!target) {
console.warn("Kein Target fuer die Zylinder-Animation");
return;
}
await API.setAnimation("pistonRod", {
target,
property: "position",
axis: [0, 0, 1],
from: 0,
to: 120,
durationMs: 900,
loop: "pingpong",
easing: "easeInOutCubic",
autoplay: false,
restoreOnStop: true
});
await API.setAnimationProgress("pistonRod", 0);
}
async function playCylinder() {
await API.playAnimation("pistonRod", true);
}
async function setCylinderStroke(strokeMm) {
await API.setAnimationValue("pistonRod", strokeMm);
}
URDF-Roboter
Die Scripting-API kann URDF-Roboter laden, deren Joints auslesen, sie ueber Jointwerte bewegen, Inverse Kinematik berechnen und Toolpaths direkt aus Projektskripten abfahren.
API.addRobot(urdfUrl, name, options)
Einen URDF-Roboter in die aktuelle Szene ladenAPI.listRobots()
Manager-geladene und Sheet-erzeugte Roboter als Snapshots zurueckgebenAPI.getRobot(target)
Roboterstatus ueber ID oder Namen lesenAPI.setActiveRobot(target)
Einen Roboter als aktiven Roboter fuer Folgeaktionen markierenAPI.getRobotJoints(target)
Joints mit Limits, Achse und aktuellem Wert auflistenAPI.setRobotJointValue(target, jointName, value, angleUnit)
Einen Joint sofort setzenAPI.setRobotJointValues(target, values, angleUnit)
Mehrere Joints gleichzeitig setzenAPI.animateRobotJointValues(target, values, durationMs, angleUnit, steps)
Joints ueber die Zeit weich animierenAPI.updateRobot(target, updates)
Basisposition, Rotation, Scale oder Sichtbarkeit des Roboters aendernAPI.getRobotEndEffectorPosition(target)
Die aktuelle Endeffektor-Position lesenAPI.solveRobotIK(target, position)
Inverse Kinematik fuer eine Ziel-TCP-Position loesenAPI.followRobotPath(target, path)
Ein Array von TCP-Wegpunkten mit optionaler Zeit pro Punkt abfahrenAPI.homeRobot(target)
Die Robot-Joints in die Home-Pose zuruecksetzenAPI.stopRobotMotion()
Den aktuellen Roboter-Motion-Run stoppenAPI.removeRobot(target)
Einen einzelnen Roboter aus der Szene entfernenAPI.clearRobots()
Alle verwalteten Roboter entfernenToolhead- und TCP-Positionierung
API.solveRobotIK() loest aktuell nur auf die Endeffektor-Position, nicht auf ein vollstaendiges Orientierungsziel. Wenn die Werkzeugausrichtung wichtig ist, kombinieren Sie TCP-Zielpunkte mit expliziten Wrist-Joint-Werten oder einer anschliessenden Joint-Korrektur.
Fuer Prozessbewegungen sollten Sie immer approach, work und retract definieren, statt direkt auf den Arbeitspunkt zu springen.
Beispiel: Einen TCP-Pfad abfahren
async function runRobotPath() {
const robots = API.listRobots();
const robot = robots[0];
if (!robot) {
console.warn("Kein URDF-Roboter im Projekt geladen");
return;
}
const joints = API.getRobotJoints(robot.id);
console.log("Verfuegbare Joints:", joints.map((joint) => joint.name));
if (joints.length > 0) {
await API.animateRobotJointValues(robot.id, {
[joints[0].name]: 20
}, 500, "degrees", 24);
}
const tcpApproach = { x: 650, y: 0, z: 980, time: 300 };
const tcpWork = { x: 650, y: 0, z: 900, time: 400 };
const tcpRetract = { x: 650, y: 0, z: 1020, time: 300 };
await API.followRobotPath(robot.id, [tcpApproach, tcpWork, tcpRetract]);
const ee = API.getRobotEndEffectorPosition(robot.id);
console.log("Finale TCP-Position:", ee);
}
Eigene Script-UI
Skripte koennen leichte Interface-Layer direkt ueber dem Editor einblenden. Das eignet sich fuer Status-Panels, eigene Tools, Dialoge und Debug-Helfer.
API.requireLibrary(name)
Unterstuetzte Runtime-Bibliotheken wie "jquery", "jquery-ui", "react" oder "babel" ladenAPI.loadExternalScript(url, globalName?)
Ein externes Script laden und optional auf einen globalen Export wartenAPI.loadExternalStyle(url, id?)
Ein externes Stylesheet einbindenAPI.createScriptMountPoint(mountId, options)
Ein absolutes oder fix positioniertes Mount-Element erzeugenAPI.removeScriptMountPoint(mountId)
Einen bestimmten Script-UI-Mount entfernenAPI.clearScriptUi()
Alle vom aktuellen Skript erzeugten Mount-Points entfernenAPI.createReactRoot(mountId, options)
Nach automatischem Laden von React einen React-Root erzeugenAPI.renderReactComponent(mountId, elementFactory, options)
Ein React-Element oder eine Component-Factory in ein Mount rendernAPI.renderReactComponentFromSource(mountId, source, options, componentName)
React-Quellcode mit Babel kompilieren und rendernAPI.openJQueryDialog(mountId, html, dialogOptions, mountOptions)
Einen jQuery-UI-Dialog aus Script-Code erzeugenBeispiel: jQuery-UI-Statusdialog oeffnen
async function showScriptStatus() {
await API.openJQueryDialog(
"script-status",
"<p>Robot setup complete.</p><p>Ready for path execution.</p>",
{ title: "Script Status", width: 360 },
{ target: "body", top: 24, right: 24 }
);
}
Beispiel: Kleines React-Panel rendern
async function showReactPanel() {
await API.renderReactComponent(
"react-status",
(React) => React.createElement(
"div",
{
style: {
padding: "14px",
borderRadius: "12px",
background: "#111827",
color: "#ffffff",
boxShadow: "0 10px 30px rgba(0,0,0,0.25)"
}
},
"Scene animation bereit"
),
{ target: "body", right: 24, bottom: 24, width: 260 }
);
}
Events und Lifecycle-Hooks
Skripte koennen auf Editorzustand, Auswahlwechsel und direkte Objektinteraktionen reagieren.
Projekt- und Auswahl-Events
projectLoaded(project)
Wird aufgerufen, wenn ein Projekt fertig geladen istprojectActivated(project)
Wird aufgerufen, wenn ein Projekt aktiv wirdONLOADED()
Wird aufgerufen, wenn DOM und Script-Umgebung bereit sindprojectSelected(project)
Wird aufgerufen, wenn ein Projekt oder Subprojekt selektiert wirdprojectDeselected(project)
Wird aufgerufen, wenn ein Projekt oder Subprojekt deselektiert wirdsheetSelected(sheet)
Wird aufgerufen, wenn ein Sheet selektiert wirdsheetDeselected(sheet)
Wird aufgerufen, wenn ein Sheet deselektiert wirdconnectorSelected(connectorData)
Wird aufgerufen, wenn ein Connector in der Szene selektiert wirdMaus-Events auf 3D-Objekten
ONENTER(object)
Hover-Enter-Helfer, der in vielen Projektskripten genutzt wirdONLEAVE(object)
Hover-Leave-Helfer, der in vielen Projektskripten genutzt wirdMouseClick(object)
Wird beim Klick auf ein Objekt aufgerufenMouseEnter(object)
Wird beim Eintritt des Cursors in ein Objekt aufgerufenMouseLeave(object)
Wird beim Verlassen des Objekts durch den Cursor aufgerufenMouseMove(object)
Wird waehrend der Bewegung ueber einem Objekt aufgerufenMouseDown(object)
Wird beim Druecken der Maustaste auf einem Objekt aufgerufenMouseUp(object)
Wird beim Loslassen der Maustaste auf einem Objekt aufgerufenBeispiel: Hervorheben bei Hover
const originalColors = new Map();
function MouseEnter(object) {
if (!originalColors.has(object.uuid) && object.material?.color) {
originalColors.set(object.uuid, object.material.color.getHex());
}
object.material?.color?.set?.("#ff6600");
object.material?.emissive?.set?.("#221100");
API.renderScene();
}
function MouseLeave(object) {
const originalColor = originalColors.get(object.uuid);
if (originalColor && object.material?.color) {
object.material.color.setHex(originalColor);
}
object.material?.emissive?.set?.("#000000");
API.renderScene();
}
Debugging
Die Runtime fuehrt eine Script-spezifische Debug-Historie und speichert den letzten Laufzeitfehler, damit Sie Fehler nicht im Blindflug suchen muessen.
console.log(), console.warn(), console.error()
Beschriftete Meldungen in die Script-Konsole schreibenAPI.getScriptDebugHistory()
Aktuelle strukturierte Debug-Eintraege zurueckgebenAPI.getLastScriptError()
Den letzten Laufzeitfehler mit Position und Codeausschnitt zurueckgebenAPI.clearScriptDebugHistory()
Debug-Historie und Error-State zuruecksetzenBeispiel: Den letzten Fehler pruefen
function inspectScriptState() {
console.log("Debug history:", API.getScriptDebugHistory());
console.log("Last script error:", API.getLastScriptError());
}
Best Practices
Diese Muster helfen dabei, Skripte vorhersehbar, schnell und gut debugbar zu halten.
- Verwenden Sie
ActiveWorkbooknur fuer Daten- und Geometrieaenderungen, die wirklich einen Modell-Rebuild benoetigen. - Nutzen Sie
API.updateSceneObject()undAPI.setAnimation()fuer fluessige Runtime-Motion, statt pro Frame Tabellenzellen zu schreiben. - Bevorzugen Sie stabile Szenen-Targets: zuerst
outputid, dann Szenenpfad, dann Objektname. - Ermitteln Sie echte Roboternamen und Joint-Namen mit
API.listRobots()undAPI.getRobotJoints(), bevor Sie Roboterbefehle ausgeben. - Planen Sie fuer Roboter-Prozessbewegungen immer Toolhead-Punkte als approach, work und retract.
- Lassen Sie in fruehen Script-Versionen bewusst
console.log()-Ausgaben stehen. Das spart spaeter viel Debug-Zeit. - Wenn Sie eine screenshot-basierte Einfuehrung in den Editor wollen, lesen Sie das Scripts Editor Workflow-Tutorial.