Gym Equipment
In this guide you will learn how to build your own configurator for a 4-way cable station using existing 3D models. You will go from having an empty application to a full interactive configurator where the user can change which equipment they want on each side.

0. Create App
Start by creating a new app:
- Go to Applications & Libraries.
- Click + Create > Application and name it Gym Equipment
Check the guide how to create an app to learn more about its overview.
1. Create Configurator
We'll start by creating a configurator with a parameter to decide the type of attachment on the right side for now.
A. Configurator Block
Continue by creating a configurator block:
- Go to Blocks.
- Click + Create > Configurator Block
- Leave
configurator1for its name and optionally rename package toASSEMBLY.
Check the guide how to create blocks to learn more about its overview.
B. Right Attachment Type
Continue by creating a parameter for the attachment type for the right side:
- At the top of the code editor, click Parameters > Text dropdown
- Put Right Attachment Type as label.
- Have the following 4 options (label -
valuerespectively):- None -
none - Cable Pull -
cablePull - Lat Pull -
latPull - Addon -
addon
- None -
- Choose None as default value.
- Click Create
2. Create Visualization
Let's generate the visualization from this configurator.
A. Visualization Block
- Go back to Blocks.
- Click + Create > Visualization Block
- Choose
configurator1as configurator and leavevisualization1for this block's name, then click Create
B. Base
Let's add the base of our 4-way station, for this:
- download BASE.step.
- at the top of the code editor, click Insert/Upload > Upload > choose BASE.step > Next: place model >Add.
Inspect the preview by rotating the camera with left-click, panning with right-click and zoom in/out with the scroll wheel.
Also check the guide how to upload files to learn more about it.
C. Right Attachment
Let's add the corresponding attachment to the the right side, for this:
- download the 3D models for each attachment:
- at the top of the code editor, click Insert/Upload > Upload > choose CABLEPULL.step > Next: place model.
- enable Condition for visibility and choose:
- as variable:
input.rightAttachmentType - as condition:
is equal - as value:
cablePull
- as variable:
Notice how the Cable Pull lands exactly on the right side by default. This is because CABLEPULL.step has been conveniently modelled in order not to need any extra positioning in DynaMaker.
Check the guide how to use conditionals to learn more about their syntax.
- Repeat the same process for the other two attachments.
See that the visualization block visualization1 now includes those 3 conditions at the end of the code.
3. Build Other Sides
Now that the right side is covered, we will repeat a similar process for the top, left and bottom sides. However additional positioning will be required.
A. Top Side
i) Configurator
Firstly, add the parameter to the configurator:
- At the top of the code-editor, click Parameters > Text dropdown
- Put Top Attachment Type as label.
- Have again the same 4 options (label -
valuerespectively):- None -
none - Cable Pull -
cablePull - Lat Pull -
latPull - Addon -
addon
- None -
- Choose None as default value.
- Click Create
ii) Visualization
Secondly, add the now-existing models with the relevant conditions:
- make sure to preview
visualization1at the left sidebar (green ▶️). - click Insert/Upload > in Select or search existing model, choose CABLEPULL > Next: place model.
- put
90degrees in the z-axis (3rd field) in Rotation. - enable Condition for visibility and choose:
- as variable:
input.topAttachmentType - as condition:
is equal - as value:
cablePull
- as variable:
- click Add.
- repeat the same process for the LATPULL and ADDON respectively.
B. (Optional) Left & Bottom Side
You can now practice on your own with the left side (180 degrees in Z) and the bottom side (-90 degrees in Z). For
this:
- create a parameter for each side (
leftAttachmentTypeandbottomAttachmentTyperespectively) with the same options. - reuse the existing models for each option respectively, naturally with different positioning rules.
In the video below it's shown that this can be done via copy-pasting the code of the current setup instead of by clicking on the buttons at the top - either way, both alternatives lead to the exact same result:
Doublecheck your resulting configurator1 & visualization1 here:
export function configurator1() {
const configurator = SKYPARAM.generateConfigurator({
parameters: {
rightAttachmentType: {
type: 'select-text',
label: 'Right Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
topAttachmentType: {
type: 'select-text',
label: 'Top Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
leftAttachmentType: {
type: 'select-text',
label: 'Left Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
bottomAttachmentType: {
type: 'select-text',
label: 'Bottom Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
},
})
return configurator
}
export function visualization1(input: SKYPARAM.ConfiguratorOutput<typeof configurator1>) {
const group = new SKYCAD.GeometryGroup()
group.addGeometry(ASSETS.STATIC_MODELS.BASE)
if (input.rightAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL)
}
if (input.rightAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL)
}
if (input.rightAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON)
}
if (input.topAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL, {
rotation: { x: 0, y: 0, z: 90, unit: 'deg' },
})
}
if (input.topAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL, {
rotation: { x: 0, y: 0, z: 90, unit: 'deg' },
})
}
if (input.topAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON, {
rotation: { x: 0, y: 0, z: 90, unit: 'deg' },
})
}
if (input.leftAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL, {
rotation: { x: 0, y: 0, z: 180, unit: 'deg' },
})
}
if (input.leftAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL, {
rotation: { x: 0, y: 0, z: 180, unit: 'deg' },
})
}
if (input.leftAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON, {
rotation: { x: 0, y: 0, z: 180, unit: 'deg' },
})
}
if (input.bottomAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL, {
rotation: { x: 0, y: 0, z: -90, unit: 'deg' },
})
}
if (input.bottomAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL, {
rotation: { x: 0, y: 0, z: -90, unit: 'deg' },
})
}
if (input.bottomAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON, {
rotation: { x: 0, y: 0, z: -90, unit: 'deg' },
})
}
return group
}
4. Preview App
In the editor you see your configurator1 and visualization1 which are ready to build the app, then:
- Go to Application Overview.
- Choose the options:
- Layout:
Configurator Sidebar and Visualization(default) - Configurator:
configurator1 - Visualization:
visualization1
- Layout:
- The app preview is now built and be briefly tested (configurator behavior, device-dependent UI and even expand the preview).
Previewing your app allows you to test everything launching the app, which helps identifying issues not only in the configurator (e.g. some missing parameter option) but also in the visualization (e.g. misplaced model).
5. Publish
Finally it's time to give access to the users!
In order to make an app public, a DynaMaker subscription is needed - you can read more about the plans here. However, if you don't have a subscription you can keep reading the tutorial to see how simple it is with only a few clicks.
Let's launch the app, for this:
- at the top-right of the Application Overview, right above the app preview, click Publish to Web
- assign a bought subscription (e.g. Standard in the video below).
- on the right, type the name of app and click Publish to Production to make your app public.
Notice that both buttons below Publish to Production become available:
- Open redirect you to the app in a new window (as shown in the video).
- Copy link that adds the app URL into your clipboard.
In any case the app URL looks something like this: https://app.dynamaker.com/deployed-applications/YOUR_APP_ID/
Check the guide how to publish to learn more about the difference between Test and Production.
Doublecheck the code of your final ASSEMBLY with its configuration1 & visualization1 here:
export function configurator1() {
const configurator = SKYPARAM.generateConfigurator({
parameters: {
rightAttachmentType: {
type: 'select-text',
label: 'Right Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
topAttachmentType: {
type: 'select-text',
label: 'Top Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
leftAttachmentType: {
type: 'select-text',
label: 'Left Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
bottomAttachmentType: {
type: 'select-text',
label: 'Bottom Attachment Type',
options: [
{ label: 'None', value: 'none' },
{ label: 'Cable Pull', value: 'cablePull' },
{ label: 'Lat Pull', value: 'latPull' },
{ label: 'Addon', value: 'addon' },
],
defaultValue: 'none',
},
},
})
return configurator
}
export function visualization1(input: SKYPARAM.ConfiguratorOutput<typeof configurator1>) {
const group = new SKYCAD.GeometryGroup()
group.addGeometry(ASSETS.STATIC_MODELS.BASE)
if (input.rightAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL)
}
if (input.rightAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL)
}
if (input.rightAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON)
}
if (input.topAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL, {
rotation: { x: 0, y: 0, z: 90, unit: 'deg' },
})
}
if (input.topAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL, {
rotation: { x: 0, y: 0, z: 90, unit: 'deg' },
})
}
if (input.topAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON, {
rotation: { x: 0, y: 0, z: 90, unit: 'deg' },
})
}
if (input.leftAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL, {
rotation: { x: 0, y: 0, z: 180, unit: 'deg' },
})
}
if (input.leftAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL, {
rotation: { x: 0, y: 0, z: 180, unit: 'deg' },
})
}
if (input.leftAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON, {
rotation: { x: 0, y: 0, z: 180, unit: 'deg' },
})
}
if (input.bottomAttachmentType === 'cablePull') {
group.addGeometry(ASSETS.STATIC_MODELS.CABLEPULL, {
rotation: { x: 0, y: 0, z: -90, unit: 'deg' },
})
}
if (input.bottomAttachmentType === 'latPull') {
group.addGeometry(ASSETS.STATIC_MODELS.LATPULL, {
rotation: { x: 0, y: 0, z: -90, unit: 'deg' },
})
}
if (input.bottomAttachmentType === 'addon') {
group.addGeometry(ASSETS.STATIC_MODELS.ADDON, {
rotation: { x: 0, y: 0, z: -90, unit: 'deg' },
})
}
return group
}
Congratulations! You are now ready to do some exercise! In the meantime, here's the app as an iframe which you can interact with: