Skip to main content

How To Import Drawings

In DynaMaker it is possible to import drawings that are already created in other software or in DynaMaker itself. The drawing formats that are available for import are PDF, DXF and SVG. As a product example, you can take any drawing, like the ones from the app of the tutorial My First Drawing.

To handle the drawing easily, it is common to store it in a component, so that it is easier to use later in the app (e.g. to get the nodes for measuring). However, other ways might be more suitable depending on how the app and its components are structured.

Let's start with a button in the app that imports the drawing. Then we will prepare the component to handle the drawing for any purpose.

A. Import Drawing Button

We will add a regular button with a specific function from the Studio that opens a modal or wizard with the required functionality, storing the layout in a component so that it's visualized through its lightweight geometry for example:

  • In the app, under UI, create a button within a tab:
const importDrawingButton = new SKYUI.Button('Import drawing', () => {
Studio.openImportWizard((result) => {
ACTIONS.setComponentLayouts(result.layouts)
Studio.requestLightweightGeometryUpdate()
}, {
// wizard optional arguments
})
}, { tooltip: 'Import drawing to the canvas', icon: STUDIO.ICONS.FILE })
  • Under ACTIONS, create a button within a tab:
export function setComponentLayouts(layouts: SKYCAD.Layout[]) {
const component = getMainComponent() // default function in template
component.clearLayouts() // will clear any existing layouts
component.setLayouts(layouts) // will store the layout in the component
}

If you click on the button, it should open the following modal:

how-to-import-drawings-1

See that when you upload a file and click + Add, the callback of Studio.openImportWizard() is triggered, giving a result with all the layouts that the uploaded drawing is split into.

Now that the button and its action are defined, we can prepare the component with the functions clearLayouts() and setLayouts().

B. Component With Drawing

To make sure the layouts within the component are not used anywhere else than in the component itself, we can make this object property private. Starting from the template, we would have:

  • In COMPONENT, you could have:
export class Component extends STUDIO.BaseComponent<CONSTANTS.Properties> {
private layouts: SKYCAD.Layout[]
constructor() {
super()

this.properties = {
depth: 100,
height: 100,
width: 100,
}

this.layouts = []
}
  • Create functions setLayouts() and clearLayouts() like:
setLayouts(layouts: SKYCAD.Layout[]) {
this.layouts = layouts
}

clearLayouts() {
this.layouts = []
}
  • Visualize the layouts through generateLightweightGeometry(), e.g. as:
generateLightweightGeometry() {
const geometryGroup = new SKYCAD.GeometryGroup()

const layouts = this.layouts
layouts.forEach(layout => {
geometryGroup.addGeometry(layout, {
plane: new SKYCAD.Plane(0, 0, 1, 0),
})
})

return geometryGroup
}
  • Optionally try adding some presets to make sure the workflow works as intended. For example:
const mainComponentPreset = new PRESET.ComponentPreset(COMPONENT.Component, {
setCameraOnUpdate: false,
})

const layout1 = new SKYCAD.Layout()
layout1.addSketch(SKYCAD.generateHexagonSketch(0, 0, 50), { lineThickness: 5 })
const layout2 = new SKYCAD.Layout()
layout2.addSketch(SKYCAD.generateCircleSketch(0, 0, 100), { lineColor: 0xff0000 })

mainComponentPreset.addCase([], {
postProcessor: (component: COMPONENT.Component) => {
component.setLayouts([layout1, layout2])
},
label: 'Both layouts',
})

mainComponentPreset.addCase([], {
postProcessor: (component: COMPONENT.Component) => {
component.setLayouts([layout1])
component.clearLayouts()
component.setLayouts([layout2])
},
label: 'Layout 2 after removing layout 1',
})

export const presetsComponent: PRESET.ComponentPreset<any>[] = [
mainComponentPreset,
]
  • Save & Update and Publish to see the changes in your app.

C. Update Lightweight Geometry

As the last step, we need to make sure the app is getting the correct geometry from the component.

  • In the app, under COMPONENTS, in updateLightweightGeometry() add:
export function updateLightweightGeometry(data: STUDIO.DataForUpdateGeometry, worldControls: STUDIO.WorldControls) {
const component = data.componentHandler.getComponents(COMPONENT1.Component)[0]
const geometry = component.generateLightweightGeometry()
worldControls.updateGeometry(geometry, { groupId: 'component-layouts' })
}

Notice that if you use:

const geometry = data.componentHandler.generateLightweightGeometry(COMPONENT1.Component)
// or
const geometry = data.componentHandler.generateAllLightweightGeometry()

you won't see the layouts stored in this.layouts because the properties didn't change so the automatic caching of the component handler ignores that the component has changed. Then, the geometry needs to be generated through component.generateLightweightGeometry() and add it accordingly.


If we put this in an app with the parameters mentioned, it could look like with this drawing example:


In this case we have added the logo as an image in a second geometry group. You can easily keep adding more within updateLightweightGeometry() like this:

export function updateLightweightGeometry(data: STUDIO.DataForUpdateGeometry, worldControls: STUDIO.WorldControls) {
// DynaMaker logo
const logoGeometry = new SKYCAD.GeometryGroup()
const logoLayout = new SKYCAD.Layout()
const logoImage = ASSETS.IMAGES.DYNAMAKER_LOGO_PNG
logoLayout.addImage(logoImage, {
position: new SKYMATH.Vector2D(-logoImage.width / 2, -logoImage.height / 2)
})
logoGeometry.addGeometry(logoLayout, {
plane: new SKYCAD.Plane(0, 0, 1, -0.1) // to make sure other layouts are on top
})
worldControls.updateGeometry(logoGeometry, { groupId: 'logo-geometry' })

// other layouts
}