What's New
Here you can read about major upgrades to the DynaMaker platform. If you experience any problems, let us know at support@dynamaker.com.
2022-05-06 Better type checking and code formatting
The code editor in DynaMaker has been upgraded to catch some common coding patterns that might lead to unexpected errors and to make the code formatting more consistent.
Strict null checks
In the video below, postPositions.find
has no guarantee that it will actually find a position. Previously, accessing
position
without checking that it is not undefined
was not reported as an error by the editor, which could lead to
errors occurring in production.
To verify that position
actually exists, you can use an if
-statement for example:
If for some reason it is not possible to do a proper check, you can use the non-null assertion operator to disable the error message. We recommend that you avoid doing this if possible, since it increases the risk of your app crashing in production:
You can read more about struct null checks here.
Code formatting
We have upgraded the formatting engine to use Prettier. You can
automatically format your code in the DynaMaker editor by pressing shiftaltf or by
pressing F1 and then search for format
.
2022-04-27 - Rotation of images
Rotation of an ImageInstance
now behaves the same as rotation of a SketchInstance
. Previously images were rotated
around their center point instead of their lower-left corner. This led to inconsistent behavior, for example when
rotating a Layout
containing both sketches and images.
Sketch (unchanged)
The blue sketch has a rotation of 0
and the red has a rotation of Math.PI / 2
.
Image before
The horizontal image has a rotation of 0
and the vertical has a rotation of Math.PI / 2
. The rotation is done around
the center of the image.
Image now
The horizontal image has a rotation of 0
and the vertical has a rotation of Math.PI / 2
. The rotation is done around
the lower left corner of the image.
Update 2022-02-09
With this update we have cleaned up the SKYCAD.Layout
API to make it easier to work with:
- Deprecated many style related functions such as
getDefaultSketchFillColor()
in favor ofgetDefaultStyle()
- Deprecated getters for individual element types such as
getDimensions()
in favor ofgetElements()
- Deprecated margins
- Deprecated size (width and height)
- Removed the default size (width and height)
- Removed the default anchors
- Renamed
cropContent ()
tocrop()
- Renamed
getContentBounds()
togetBounds()
- Renamed
rotateContent ()
torotate()
- Renamed
scaleContent ()
toscale()
- Renamed
translateContent ()
totranslate()
Update 2022-02-01
This update contains the following changes:
- New tutorial: My First App
- Simplified application template
- Simplified UI template
- Simplified component template
New tutorial: My First App
A new tutorial My First App has been added. It covers the very basics of how to create an application, from template to deployment.
The rest of the tutorials have been updated to fit with the new simplified project and app templates.
Simplified application template
The new application template comes with no components or drawings out-of-the-box. By creating and connecting all the parts of the application, we hope that you as a developer will gain a better understanding of how your application works. Check the new tutorial My First App which covers the first steps of creating an application!
Simplified UI template
Since there are no components in the default project template, the new UI template should be much easier to grasp. Most of the template code is now in the UI tab when starting. As your application grows, you can structure your code into the COMPONENTS, ACTIONS and CONSTANTS tabs.
Although no component is added by default, there are a few lines of commented code that can help you when importing your first component.
Simplified component template
There have been a few changes in the component template as well to make it easier to get started with. Just like in the
UI, most template code have been moved to the COMPONENT tab. As your component grows more complex, you should
still move geometry logic to GEOM3D and GEOM2D, but when starting it is all contained within
generateGeometry()
in the Component
itself.
Update 2021-11-04
Simplified SKYMATH API
The SKYMATH module has been reworked to be easier to understand and use! Many existing functions have been deprecated and will show up as strikethrough in the code. We recommend that you start using the new functions, but the deprecated function will continue to work as before.
The deprecation message (highlighted in the image above) will give you a hint of what function you can use instead of
the deprecated one. In this example, you can replace the call to SKYMATH.addVectors2D(v1, v2)
with SKYMATH.add(v1,
v2)
.
Many of the new functions have overload signatures, which means that the same function can work with different input.
For example, the new SKYMATH.add()
works in both 2D and 3D and replaces both SKYMATH.addVectors2D()
and
SKYMATH.addVectors3D()
. It can also add two instances of the new SKYMATH.Matrix
class!
SKYMATH.add(new SKYMATH.Vector2D(1, 2), new SKYMATH.Vector2D(2, 1)) // returns new SKYMATH.Vector2D(3, 3)
SKYMATH.add(new SKYMATH.Vector3D(1, 2, 3), new SKYMATH.Vector3D(3, 2, 1)) // returns new SKYMATH.Vector2D(4, 4, 4)
You can see all the overloads by clicking the arrows (or using the up and down arrows on your keyboard) next to the function signature in the code editor.
You can read more about function overloads in the official TypeScript handbook.
Update 2021-10-21
Geometry loading effect
When geometry is being updated, after a Studio.requestGeometryUpdate()
, the previous geometry will become blurred to
indicate to the user that an update is running.
You can change this loading effect using CSS. For example, to make the geometry 50% grayscale in addition to the blur effect, add the following to the STYLE tab:
canvas.loading {
filter: blur(2px) grayscale(50%);
}
Applications created before this change was released can opt-in by adding a style rule in the STYLE tab. Here is the default rule used in new applications:
canvas.loading {
filter: blur(2px);
}
You can opt-out of this change altogether in the ADVANCED tab:
export function productConfigurationFactory(): STUDIO.IProductConfiguration {
return {
disableLoadingEffectOnGeometryUpdate: true,
// other settings...
}
}
Update 2021-10-07
Simplified camera API
The functions used for handling the camera have been reworked and many existing functions have been deprecated. Although we recommend that you start using the new camera functions, the deprecated function will continue to work as before, but will show up as strikethorugh in the code:
There are now four main camera functions:
Studio.setCameraToFitBounds()
Studio.setCameraPosition()
Studio.setCameraTarget()
Studio.updateCameraSettings()
You can read more about the new camera API here!
Update 2021-08-30
Editor layout change
We have simplified the layout of how you access the different files in the code editor. By flattening the file menu to a single list on the right hand side, you can open any file in the editor with one click.
Easier access to the Studio service when working in UI
The UI template has been updated so that the Studio
service is global in the UI file. This only applies to
new projects that you create from this update and forward. If you want you can create a new project and copy-paste this
change into your existing project.
Update 2021-06-20
Some CAD-related classes and functions have been moved from SKYMATH
to SKYCAD
. Your code has been automatically
updated to reflect these changes.
RefPlane moved and renamed
SKYMATH.RefPlane
is now SKYCAD.Plane
.
Bounds moved
SKYMATH.Bounds2D
and SKYMATH.Bounds3D
are now SKYCAD.Bounds2D
and SKYCAD.Bounds3D
respectively.
Update 2021-06-01
This update to DynaMaker simplifies working with the CAD libraries by merging the whole SKYSKETCH namespace into the SKYCAD namespace.
How does this update affect existing projects?
All references to SKYSKETCH
have been changed to SKYCAD
, so this update should be non-breaking. Your projects will
work just like before, but instead of writing new SKYSKETCH.Layout()
to create a new Layout
, you write new
SKYCAD.Layout()
instead.
Update 2021-02-17
This update to DynaMaker, which should not break any existing projects, makes it easier to use the
ComponentHandler
and brings out-of-the-box support for save and load.
How does this update affect existing projects?
This update introduces a new pattern of interacting with the ComponentHandler. Existing projects may choose to continue using the old pattern and can ignore the changes described below. If you create a new component in an existing project, you may have to update it manually to make it look like before. Another way, which may be easier, is to fork an existing component in your project and build from there.
Changes to the ComponentHandler
Define components
The ComponentHandler function defineComponent()
is no longer needed and should not be used.
Add components
You no longer have to add a type string when adding components to the ComponentHandler.
// old
componentHandler.add('accessory', new ACCESSORY.Component())
// new
componentHandler.add(new ACCESSORY.Component())
If you need to separate the same component class into logical groups, you may do so using tags
.
// old
componentHandler.add('accessory-top', new ACCESSORY.Component())
componentHandler.add('accessory-bottom', new ACCESSORY.Component())
const topAccessories = componentHandler.getInstances('accessory-top')
// new
componentHandler.add(new ACCESSORY.Component(), { tags: ['top'] })
componentHandler.add(new ACCESSORY.Component(), { tags: ['bottom'] })
const topAccessories = componentHandler
.getInstances(ACCESSORY.Component)
.filter(inst => inst.hasTag('top'))
Get components, instances and bundles
// old
componentHandler.getInstances('accessory')
componentHandler.getComponents('accessory')
componentHandler.getBundles('accessory')
// new (provides code completion!)
componentHandler.getInstances(ACCESSORY.Component)
componentHandler.getComponents(ACCESSORY.Component)
componentHandler.getBundles(ACCESSORY.Component)
Clear a specific component
// old
componentHandler.clear('accessory')
// new, by class
componentHandler.clear(ACCESSORY.Component)
// new, by tag
componentHandler.clear('my-tag')
New application and component templates
When you create a new project or component, you might notice that the template has changed with this update.
Component
- Extending STUDIO.BaseComponent
Components now extend
the STUDIO.BaseComponent
class, which adds functionality such as the getProperty
function to
your component automatically.
- Constructor arguments
It is best practice to have a Component constructor without input arguments. If you need to change the values of the
properties you should call component.setProperties({ ... })
after creating the component. The template has been
updated to reflect this.
// old
constructor(args: Partial<CONSTANTS.Properties> = {}) {
const width = args.width ?? 100
const depth = args.depth ?? 100
const height = args.height ?? 100
this.properties = { width, depth, height }
}
// new
constructor() {
super()
this.setProperties({
depth: 100,
height: 100,
width: 100,
})
}
Save and load
If your project has authentication such as JSON Web Tokens or Auth0 enabled, the new application template together with the updated ComponentHandler allows for saving and loading configurations in your deployed project by default.
While developing
You can now test save and load directly in the UI Editor editor.
Update 2020-10-20
This update to DynaMaker, which should not break any existing projects, makes it easier to create and use geometry.
Deprecations
You will notice that some classes and functions that you've used previously have been deprecated. Deprecated classes and functions still work, but should be avoided in new code that you write.
Deprecated classes and functions will appear as strikethrough in the editor
Action Events
The way that actions related to the product are called from the UI code has changed for new projects. The new way brings a better developer experience through code completion and type checking.
// old way
Studio.actionEvent('generate-configurator')
// new way
ACTIONS.generateConfigurator()
The Geometry API
The way that we create and group geometry (models and sketches) has changed with this update.
- The new class
SKYCAD.GeometryGroup
should be used for grouping geometry (parent-child structure) SKYCAD.ModelInstance
should no longer be used as a parent of other models viaaddChildInstance()
ComponentInstance.getModelInstance()
is replaced byComponentInstance.generateGeometry()
and now returns aSKYCAD.GeometryGroup
SKYCAD.GeometryOnPlane
has been deprecated in favor of the similarSKYCAD.LayoutOnPlane
SKYCAD.Model
has been renamed toSKYCAD.ParametricModel
to differentiate it fromSKYCAD.MeshModel
SKYCAD.ModelMaterial
has been renamed toSKYCAD.Material
Geometry And The Component Handler
The component handler has been updated with some new functionality that makes it simple to gather all the geometry from your components!
componentHandler.generateAllGeometry(): SKYCAD.GeometryGroup
componentHandler.generateGeometry(componentType: string): SKYCAD.GeometryGroup
componentHandler.generateAllLightweightGeometry(): SKYCAD.GeometryGroup
componentHandler.generateLightweightGeometry(componentType: string): SKYCAD.GeometryGroup
These functions position the geometry for each component instance. They require that your components implement the
generateGeometry()
and generateLightweightGeometry()
functions respectively.
Updating The Scene
For new projects, getModels()
and getSketches()
in the COMPONENTS tab of the UI Editor have been
replaced by updateGeometry()
and updateLightweightGeometry()
, to give you more fine-grained control over what
geometry should update and when.
// the old way
export function getModels(manager: STUDIO.Manager) {
// ...
}
export function getSketches(manager: STUDIO.Manager) {
// ...
}
// the new way
/**
* Add new Geometry to the scene depending on app state
*/
export function updateGeometry(data: STUDIO.DataForUpdateGeometry, worldControls: STUDIO.WorldControls) {
const geometryGroup = new SKYCAD.GeometryGroup()
switch (data.designStep) {
case CONSTANTS.DESIGN_STEP.PRODUCT:
geometryGroup.addGeometry(data.componentHandler.generateGeometry(CONSTANTS.COMPONENT_TYPE.MAIN))
break
case CONSTANTS.DESIGN_STEP.EXPORT:
geometryGroup.addGeometry(data.componentHandler.generateGeometry(CONSTANTS.COMPONENT_TYPE.MAIN))
break
}
worldControls.updateGeometry(geometryGroup, { groupId: 'primary' })
}
/**
* Optional lightweight geometry
*/
export function updateLightweightGeometry(data: STUDIO.DataForUpdateGeometry, worldControls: STUDIO.WorldControls) {
const geometry = data.componentHandler.generateAllLightweightGeometry()
worldControls.updateGeometry(geometry, { groupId: 'lightweight' })
}
Instead of calling Studio.update()
you should use Studio.requestGeometryUpdate()
and
Studio.requestLightweightGeometryUpdate()
together with this new update geometry pattern.
Components And The Configurator
New components created from this point forward have a new pattern for generating their configurator(s). Instead of
implementing the configure()
function on the component, you should export one or more functions from the
You can switch between different configurators with the dropdown in the upper left corner
In the application, use the generator functions to generate the configurator instead of calling configure()
.
// old way
export function actionEvent(type: string, args: any, manager: STUDIO.Manager) {
// ...
switch (type) {
case 'configure-component': return component.configure()
}
}
// new way
export function configureMainComponent() {
const component = getMainComponent()
return COMPONENT1.generateConfigurator(component)
}