Direct edit scripts - HiStructClient/femcad-doc GitHub Wiki

State machine based direct edit scripting

Examples

Instructions

  1. Add button on input page for starting the script.

    res.fit.InputItemAction {
       HtmlContent = "dimension tool",
       ValidationTrigger = "dimensionToolActionScriptDone(%userInput)",
       Behavior = "direct-edit-script:dimensionToolActionScriptDefinition",
    }
    
  2. Add path to validation trigger that reffers to a function that takes one parameter. Put %userInput placeholder as an argument. It will be replaced with the object containing input from the user when the state machine reaches its final state (e.g. positions of pointer clicks). The exact format of the user input object is derived from the state machine definition.

  3. Add the behavior property with the prefix: direct-edit-script: following the path to the object representing direct edit script definition. For local paths, start the script name with ..

  4. Add object containing direct edit script definition (state machine)

  5. Add parametrized validation trigger

    dimensionToolActionScriptDone = userInput => site.construct.geometryVolumes.inputs[0].dimensionToolActionScriptTriggerFn(userInput)
    ...
    dimensionToolActionScriptTriggerFn := userInput => {
        Constraints = [
          {
              Variable = "site.construct.geometryVolumes.inputs[0].dimensionToolPoints",
              Condition = False,
              Init = [ 
                  userInput.parameters.firstPoint.values[0], 
                  userInput.parameters.secondPoint.values[0], 
                  userInput.parameters.thirdPoint.values[0] 
              ],
              Explanation = "dimension tool done",
          }
        ]
     }
    
  6. Add input variable for storing user input

    dimensionToolPoints := []
    ...
    res.fit.InputItemArray {
        Identifier = "dimensionToolPoints",
        InputTypes = [
            res.fit.InputItemArray {
                InputTypes = [ res.fit.InputItemDouble ],
            },
        ],
    },
    

Definition of state machine

{
   id = "script-name",
   formatVersion = "0.2",
   stateMachine = {
      data = {
            parameters = {
               targetPoint = { type = "point-value", value = [10, 2, 0] }
            }
      },
      parentLcsType? = "gcs" | "selection" | "custom",
      lcs? = {
            origin = [0, 0, 0],
            axes = [1, 0, 0], [0, 1, 0], [0, 0, 1](/HiStructClient/femcad-doc/wiki/1,-0,-0],-[0,-1,-0],-[0,-0,-1)
      },
      states = [
            { id = "0", visuals = [{ type = "dot", geometry = { type = "cursor" } }] },
            { id = "1" }
      ],
      transitions = [
            {
               from = "0",
               to = "1",
               condition = {
                  type = "select-point", point = { type = "point", id = "targetPoint" }
               },
               # or conditions = [{...}, ...],
               visuals = [{ type = "dot", geometry = { type = "point", id = "targetPoint" }, options = { color = "#FF0000" } }]
            }
      ],
      initState = "0",
      finalStates = ["1"]
   }
}

Parametric geometry

ParametricPoint

  • cursor

    { type = "cursor" }

  • point

    { type = "point", id = "parameterName", range? = ".." }

  • point-value

    { type = "point-value", value = [0, 0, 0] }

  • point-values

    { type = "point-values", values = [1, 1, 0], [2, -1, 0](/HiStructClient/femcad-doc/wiki/1,-1,-0],-[2,--1,-0) }

  • point-projected-to-ray

    { type = "point-projected-to-ray", point = ParametricPoint, ray = ParametricRay, clampToStart? = False }

  • point-projected-to-line

    { type = "point-projected-to-line", point = ParametricPoint, line = ParametricLine, clampToStart? = False, clampToEnd? = False }

  • point-projected-to-plane

    { type = "point-projected-to-plane", point = ParametricPoint, plane = ParametricPlane }

  • point-on-line-segment

    { type = "point-on-line-segment", line = ParametricLine, parameter? = ParametricScalar, fromStart? = ParametricScalar, fromEnd? = ParametricScalar }

  • translate-point

    { type = "translate-point", point = ParametricPoint, direction = ParametricVector, distance = ParametricScalar }

ParametricPointGrid

{ type = "point-grid", origin? = ParametricPoint, xAxis = GridAxis, yAxis = GridAxis }

GridAxis

{
  direction? = ParametricVector,   # unit vector that defining the grid plane (x or y axis of grid's lcs), if undefined GCS is used
  step = ParametricScalar,         # distance between individual snap points in a given axis
  min? = ParametricScalar,         # lower limit of the grid as the distance from the origin in a given axis, can be undefined
  max? = ParametricScalar,         # upper limit of the grid as the distance from the origin in a given axis, can be undefined
}

ParametricVector

  • vector

    { type = "vector", id = "parameterName", range? = ".." }

  • vector-value

    { type = "vector-value", value = [0, 0, 1] }

  • vector-values

    { type = "vector-values", values = [1, 0, 0], [0, 1, 0], [0, 0, 1](/HiStructClient/femcad-doc/wiki/1,-0,-0],-[0,-1,-0],-[0,-0,-1) }

  • parallel-vector

    { type = "parallel-vector", line = ParametricLine }

  • perpendicular-vector

    { type = "perpendicular-vector", line = ParametricLine, up? = ParametricVector }

  • camera-direction

    { type = "camera-direction" }

  • camera-azimuth

    { type = "camera-azimuth" }

  • rotate-vector

    { type = "rotate-vector", vector = ParametricVector, axis = ParametricVector, angle = ParametricScalar }

ParametricScalar

  • scalar

    { type = "scalar", id = "parameterName", range? = ".." }

  • scalar-value

    { type = "scalar-value", value = 0 }

  • scalar-values

    { type = "scalar-values", values = [3, 5.6, -9, 4] }

  • line-length

    { type = "line-length", line = ParametricLine }

  • product

    { type = "product", left = ParametricScalar, right = ParametricScalar }

  • sum

    { type = "sum", left = ParametricScalar, right = ParametricScalar }

  • angle

    { type = "angle", v1 = ParametricVector, v2 = ParametricVector, axis = ParametricVector }

  • point-coordinate

    { type = "point-coordinate", point = ParametricPoint, index = 0 | 1 | 2 }

  • vector-component

    { type = "vector-component", point = ParametricVector, index = 0 | 1 | 2 }

ParametricText

  • text

    { type = "text", id = "parameterName", range? = ".." }

  • text-value

    { type = "text-value", value = "abc" }

  • text-values

    { type = "text-values", values = ["a", "b", "c"] }

  • text-from-scalar

    { type = "text-from-scalar", scalar = ParametricScalar, format? = "{0.00} m" }

  • text-join

    { type = "text-join", texts = ParametricText[], separator? = "; " }

ParametricLine

Two element typle consisting of start and end points of the line

[ParametricPoint, ParametricPoint]

ParametricRay

Two element tuple of starting point and direction vector

[ParametricPoint, ParametricVector]

ParametricPlane

Two element tuple of point on plane and normal vector

[ParametricPoint, ParametricVector]

ParametricTriangleFan

Array of ParametricPoint elements

Visuals

// TODO: describe difference between state and transition visuals

  • state visuals
  • transition visuals

dot

{ type = "dot", geometry = ParametricPoint | ParametricPointGrid, options? = { color? = "#FFFFFF", size? = 5, alwaysVisible? = False } }

line

{ type = "line", geometry = ParametricLine, options? = { color? = "#FFFFFF", dashSize? = 2, gapSize? = 2, alwaysVisible? = False } }

ray

{ type = "ray", geometry = ParametricRay, options? = { color? = "#FFFFFF", dashSize? = 2, gapSize? = 2, alwaysVisible? = True } }

polyline

{ type = "polyline", geometry = ParametricPoint[], options? = { color? = "#FFFFFF", dashSize? = 2, gapSize? = 2, alwaysVisible? = False } }

triangle-fan

{ type = "triangle-fan", geometry = ParametricPoint[], options? = { color? = "#FFFFFF", opacity? = 1.0 } }

text-label

{ type = "text-label", position = ParametricPoint, text = ParametricText }

text-tooltip

{ type = "text-tooltip", position = ParametricPoint, text = ParametricText }

scene-model

{ type = "scene-model", source? = "model-path" | "hiscene-url" | "selection" | "model-url", path? = "...", pathParamId? = "...", transform? = { ... }, allowInteractions?: False, sizeAttenuationFactor?: 1 }

source, path

Parameter source together with path defines the location of scene model definition.

  • Scene model defined using modelPath that references existing model in scene

    { type = "scene-model", source? = "model-path", path = "gbDetailedRoofOpeningModels.dParts[0]", transform = { type = "change-of-basis", new = { origin = { type = "point", id = "endPoint" } } } }

  • Scene model defined using static hiscene in external storage

    { type = "scene-model", source = "hiscene-url", path = "https://histructstatic.blob.core.windows.net/models/hiscenes/rotate-roller-01.json", transform = { type = "change-of-basis", new = { origin = { type = "point", id = "rotationPoint" }, xAxis = { type = "vector", id = "x" }, yAxis = { type = "vector", id = "y" }, zAxis = { type = "vector", id = "z" } } }, sizeAttenuationFactor = 50 }

  • Scene model created from currently selected model(s) in scene

    { type = "scene-model", source = "selection", transform = { ... } }

  • Scene model created from external model

    { type = "scene-model", source = "model-url", path? = "https://cdn.histruct.com/external-objects/user-import/...", pathParamId? = "importedFileUrl" }

transform

allowInteractions

sizeAttenuationFactor

Transitions

Transition definition

{
    from = StateId,
    to = StateId,
    condition? = TransitionCondition,
    conditions? = TransitionCondition[],
    visuals? = Visual[],
    saveAs? = ScriptParameters,
}

Transition conditions

// TODO: describe difference between "select-point" and "enter-point" conditions

select-point

{ type = "select-point", point = ParametricPoint | ParametricPointGrid, saveAsPointId? = "inputParameter" }

enter-point

{ type = "enter-point", point = ParametricPoint | ParametricPointGrid, saveAsPointId? = "inputParameter" }

select-vertex

{ type = "select-vertex", saveAsPointId? = "inputParameter" }

select-edge

{ type = "select-edge", saveAsPointId? = "pointOnEdgeId", saveAsLineIds? = ["edgeStartId", "edgeEndId"] }

select-face

{ type = "select-face", saveAsPointId? = "pointOnFaceId", saveAsPlaneIds? = ["planeOriginPointId", "planeNormalVectorId"] }

enter-text

{ type = "enter-text", format? = "{text}" | "{float}" | "{integer}" | "@{float},{float}" | ..., submitKey? = "key-name", saveAsIds? = ["value1", "value2", ...] }

open-file

{ type = "open-file", format = "obj" | "dxf", saveAsExternalObjectUrlId? = "importedFileUrl" }