Experte

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.

confBuild Scripting Uebersicht

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.

Namespace Wofuer er verwendet wird
ActiveWorkbook Tabellen lesen, schreiben, Bereiche abfragen und Hilfsfunktionen fuer Sheets
API UI-Updates, Scenegraph-Helfer, Animationen, Roboter, Script-UI und Debugging
scene Szenenbezogene Helfer wie das Erstellen und Aktualisieren von Connectors

Refresh-Regeln

  • Rufen Sie await API.updateUI() auf, nachdem Sie Tabellenzellen mit ActiveWorkbook geaendert 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.

Spreadsheet Scripting Beispiel
Funktion Beschreibung
ActiveWorkbook.getCellSerialized(address) Aktuellen serialisierten Zellwert lesen
ActiveWorkbook.getCellFormula(address) Zellenformel lesen
ActiveWorkbook.setCellContents(address, value) Wert oder Formel in eine Zelle schreiben
ActiveWorkbook.getRangeValues(range) Einen Zellbereich auslesen
ActiveWorkbook.getRangeFormulas(range) Formeln eines Bereichs auslesen
ActiveWorkbook.getSheetDimensions(sheetId) Zeilen- und Spaltenanzahl eines Sheets zurueckgeben
ActiveWorkbook.simpleCellAddressFromString("B5", 0) Eine Tabellenadresse in ein 0-basiertes Adressobjekt umwandeln
ActiveWorkbook.simpleCellAddressToString(address, 0) Ein Adressobjekt wieder in Tabellen-Notation umwandeln

Beispiel: 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.

Funktion Beschreibung
API.getSelectedSceneObject() Das aktuell selektierte THREE.js-Objekt zurueckgeben
API.getSceneObject(target) Ein Objekt ueber outputid, Szenenpfad, Namen oder Objektreferenz aufloesen
API.getSceneObjectState(target) Einen einfachen Snapshot von Position, Rotation, Scale, Sichtbarkeit und Parent-Info lesen
API.updateSceneObject(target, updates) Absolute oder relative Position, Rotation, Scale, Sichtbarkeit, Name oder userData aendern
API.renderScene(force?) Den Viewport nach direkten Scenegraph-Aenderungen neu rendern

Unterstuetzte 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.

Funktion Beschreibung
API.animate(target, config) Eine Animation direkt aus Target und Konfiguration erzeugen
API.setAnimation(id, config) Eine benannte Animation erstellen oder ersetzen
API.playAnimation(id?, restart?) Eine Animation oder alle Animationen abspielen
API.pauseAnimation(id?) Eine Animation oder alle Animationen pausieren
API.stopAnimation(id?, restore?) Die Bewegung stoppen und optional die urspruengliche Transform-Basis wiederherstellen
API.setAnimationProgress(id, progress) Den Fortschritt zwischen 0 und 1 setzen
API.setAnimationValue(id, value) Direkt zu einem konkreten Wert zwischen from und to springen
API.getAnimation(id) Status, Richtung, Dauer und Fortschritt einer Animation lesen
API.listAnimations(id?) Alle Animationen oder eine passende Gruppe auflisten

Referenz 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.

Funktion Beschreibung
API.addRobot(urdfUrl, name, options) Einen URDF-Roboter in die aktuelle Szene laden
API.listRobots() Manager-geladene und Sheet-erzeugte Roboter als Snapshots zurueckgeben
API.getRobot(target) Roboterstatus ueber ID oder Namen lesen
API.setActiveRobot(target) Einen Roboter als aktiven Roboter fuer Folgeaktionen markieren
API.getRobotJoints(target) Joints mit Limits, Achse und aktuellem Wert auflisten
API.setRobotJointValue(target, jointName, value, angleUnit) Einen Joint sofort setzen
API.setRobotJointValues(target, values, angleUnit) Mehrere Joints gleichzeitig setzen
API.animateRobotJointValues(target, values, durationMs, angleUnit, steps) Joints ueber die Zeit weich animieren
API.updateRobot(target, updates) Basisposition, Rotation, Scale oder Sichtbarkeit des Roboters aendern
API.getRobotEndEffectorPosition(target) Die aktuelle Endeffektor-Position lesen
API.solveRobotIK(target, position) Inverse Kinematik fuer eine Ziel-TCP-Position loesen
API.followRobotPath(target, path) Ein Array von TCP-Wegpunkten mit optionaler Zeit pro Punkt abfahren
API.homeRobot(target) Die Robot-Joints in die Home-Pose zuruecksetzen
API.stopRobotMotion() Den aktuellen Roboter-Motion-Run stoppen
API.removeRobot(target) Einen einzelnen Roboter aus der Szene entfernen
API.clearRobots() Alle verwalteten Roboter entfernen

Toolhead- 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.

Funktion Beschreibung
API.requireLibrary(name) Unterstuetzte Runtime-Bibliotheken wie "jquery", "jquery-ui", "react" oder "babel" laden
API.loadExternalScript(url, globalName?) Ein externes Script laden und optional auf einen globalen Export warten
API.loadExternalStyle(url, id?) Ein externes Stylesheet einbinden
API.createScriptMountPoint(mountId, options) Ein absolutes oder fix positioniertes Mount-Element erzeugen
API.removeScriptMountPoint(mountId) Einen bestimmten Script-UI-Mount entfernen
API.clearScriptUi() Alle vom aktuellen Skript erzeugten Mount-Points entfernen
API.createReactRoot(mountId, options) Nach automatischem Laden von React einen React-Root erzeugen
API.renderReactComponent(mountId, elementFactory, options) Ein React-Element oder eine Component-Factory in ein Mount rendern
API.renderReactComponentFromSource(mountId, source, options, componentName) React-Quellcode mit Babel kompilieren und rendern
API.openJQueryDialog(mountId, html, dialogOptions, mountOptions) Einen jQuery-UI-Dialog aus Script-Code erzeugen

Beispiel: 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

Event Beschreibung
projectLoaded(project) Wird aufgerufen, wenn ein Projekt fertig geladen ist
projectActivated(project) Wird aufgerufen, wenn ein Projekt aktiv wird
ONLOADED() Wird aufgerufen, wenn DOM und Script-Umgebung bereit sind
projectSelected(project) Wird aufgerufen, wenn ein Projekt oder Subprojekt selektiert wird
projectDeselected(project) Wird aufgerufen, wenn ein Projekt oder Subprojekt deselektiert wird
sheetSelected(sheet) Wird aufgerufen, wenn ein Sheet selektiert wird
sheetDeselected(sheet) Wird aufgerufen, wenn ein Sheet deselektiert wird
connectorSelected(connectorData) Wird aufgerufen, wenn ein Connector in der Szene selektiert wird

Maus-Events auf 3D-Objekten

Event Beschreibung
ONENTER(object) Hover-Enter-Helfer, der in vielen Projektskripten genutzt wird
ONLEAVE(object) Hover-Leave-Helfer, der in vielen Projektskripten genutzt wird
MouseClick(object) Wird beim Klick auf ein Objekt aufgerufen
MouseEnter(object) Wird beim Eintritt des Cursors in ein Objekt aufgerufen
MouseLeave(object) Wird beim Verlassen des Objekts durch den Cursor aufgerufen
MouseMove(object) Wird waehrend der Bewegung ueber einem Objekt aufgerufen
MouseDown(object) Wird beim Druecken der Maustaste auf einem Objekt aufgerufen
MouseUp(object) Wird beim Loslassen der Maustaste auf einem Objekt aufgerufen

Beispiel: 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.

Funktion Beschreibung
console.log(), console.warn(), console.error() Beschriftete Meldungen in die Script-Konsole schreiben
API.getScriptDebugHistory() Aktuelle strukturierte Debug-Eintraege zurueckgeben
API.getLastScriptError() Den letzten Laufzeitfehler mit Position und Codeausschnitt zurueckgeben
API.clearScriptDebugHistory() Debug-Historie und Error-State zuruecksetzen

Beispiel: 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 ActiveWorkbook nur fuer Daten- und Geometrieaenderungen, die wirklich einen Modell-Rebuild benoetigen.
  • Nutzen Sie API.updateSceneObject() und API.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() und API.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.

Bereit zum Programmieren?

Setzen Sie Ihr Wissen in die Praxis um

Jetzt starten