Skip to content

Releases

Skpwright 0.6.0

Choose a tag to compare

@granroth granroth released this 06 Nov 23:24

Skpwright 0.6.0 reads and writes every and all SketchUp releases from 3 to 2027!

The project was called OpenSKP up to 0.5.0.

Releases and formats

  • Files of releases 3 to 8, 2013 to 2016 and 2018 to 2020 read whole through one grammar and write back byte for byte. Model::write_as writes a model as any release 3 to 2020, and returns notes on what the target release cannot hold.
  • Releases 2021 to 2025 are supported through the 2026 container, which gates on its model revision. Files written at revision 17 or 18 open in current SketchUp.
  • Post-2017 features read into Model.features: hatch patterns, layer folders, line styles, physically based materials, environments, the coordinate reference system, snaps and procedures.
  • A 2017 radial dimension that names no edge reads whole instead of falling back to the byte scan.

Renamed

  • The crates are skpwright, skpwright-cli and skpwright-capi. The command is skpwright, and the C library is libskpwright, with its header include/skpwright.h and the skpwright_ function prefix. The 0.5.0 and earlier versions stay on crates.io as the openskp crates.

Upgrading from 0.5

  • Document17 is StreamDocument and takes a release. Model::write_2017 is write_as(path, Release::R2017). Container::Carchive2017 is Container::Stream, and the JSON reports "stream".
  • Model, RenderingOptions, RadialDimension and Diagnostic gain fields and variants, so struct literals that name every field and exhaustive matches must add them.

See the changelog for the full list.

skpwright = "0.6"

OpenSKP 0.5.0

Choose a tag to compare

@granroth granroth released this 11 Oct 23:05

OpenSKP 0.5.0 writes SketchUp files: 2026 and 2017, authored from a model or edited in place.

Writing

  • Model::write and Model::write_2017 author either container from any model. SketchUp Make 2017 and SketchUp for Web open the results.
  • Document (2026) and Document17 (2017) reproduce an unedited file byte for byte, and edit vertices, transforms, visibility and material colors in place.
  • WriteEnv fixes the save time and seed, so the same input writes the same bytes, including on WebAssembly.

Reading

  • 2017 files are read by a whole-file grammar. Every 2017 corpus file reproduces byte for byte from it.
  • New on both containers: radial dimensions, 3D polylines, placed images, matched photos, sketchy edges, thumbnails, classifications, and attribute dictionaries on every object.
  • A 2017 file with tens of thousands of entity lists no longer spends over a minute resolving them.

CLI and C ABI

  • openskp gains convert, verify and copy, with exit status 0, 1 for a file error, and 2 for a usage error. Install it with cargo install openskp-cli.
  • The C ABI gains openskp_write and openskp_write_2017.

Upgrading from 0.4

  • Material opacity is now one minus the stored transparency. 0.4 returned the stored value, so translucent materials read differently.
  • Public structs, Material variants and Diagnostic gain fields and variants. Struct literals and exhaustive matches must add them; most types now implement Default.
  • Guide, texture-size and attribute values are no longer rounded to five decimals.
  • The CLI rejects unknown options and extra arguments.
openskp = "0.5"

OpenSKP 0.4.1

Choose a tag to compare

@granroth granroth released this 29 Sep 00:58

A model can cut on a section plane without any scene recording it: each entity list keeps track of the plane currently cutting it. OpenSKP 0.4.1 reads that plane on both containers, so a consumer can tell the cutting plane from planes merely placed.

The active section plane

  • GeometryRun::active_section is the persistent id of the plane currently cutting that run's entity list, or None when no plane is active. It names one of the run's own sections. See docs/SDK.md.
  • 2026 container: every entity container records it (0x1394, present only while a plane is active), so definitions report their own active plane.
  • 2017 format: the root tail's first pointer, null in every file without a cut, is a back-reference to the active plane's store-map slot (docs/SKP_FORMAT.md §4). It is read for the root run; a definition's own active plane is not decoded on 2017 and reads None.
  • The 2017 marker was isolated with a new minimal pair, corpus/2017/section-plane-deactivated.skp: two planes whose records are byte-identical, the second one active. A section plane record carries no active flag.

Compatibility

  • GeometryRun gains the public field active_section. Code that only reads GeometryRun is unaffected; code that constructs it with a struct literal or destructures it exhaustively must add the field.
  • No other API, format, or dependency changes.

OpenSKP 0.4.0

Choose a tag to compare

@granroth granroth released this 28 Sep 16:18

OpenSKP reads the SketchUp 2026 container, the format every current SketchUp release saves, and treats it as the primary target. The 2017 format stays fully supported, and both readers produce the same Model.

SketchUp 2026 files

  • Model::parse opens 2026 files: a ZIP container whose model.dat is a tree of u16 tag | u32 length | payload records, with XML materials beside their textures. docs/SKP_FORMAT.md §16 specifies it, decoded clean-room against 72 pairs of 2017 files and their 2026 saves.
  • Every 2017 corpus file has a 2026 twin, and each twin reads equivalent to its original in geometry, materials, layers, UVs, scenes, guides and document settings. The third-party benchmark meets its COLLADA oracle in both containers.
  • A damaged record no longer fails the file. The reader keeps everything before the damage and records the loss as Diagnostic::Skipped; record tags it does not know are reported instead of dropped. Buffers are reserved fallibly, so an oversized model returns an error instead of aborting.
  • One runtime dependency, miniz_oxide, for DEFLATE.

Typed document settings

Camera, rendering options, shadows, units, styles and watermarks, fonts, texts, dimensions, axes, text and dimension defaults, animation and geo-location are typed fields on Model on both paths. Scenes carry their saved parts instead of names only. See docs/SDK.md.

The 2017 walk

  • Production-scale models, up to a 464 MB furnished house, read on the continuous walk. A store-map slot shrank from 256 to 64 bytes, and map growth is fallible. An opt-in test (OPENSKP_EXTERNAL_MODELS) checks local third-party files.
  • A mis-sized construction point or section plane could silently drop every root entity after it. Both bodies are now sized exactly, and the walk requires the root tail where the root list ends.

Breaking changes

  • Container gains Zip, and Model::parse returns a model for 2026 files instead of an error.
  • Model::format_guid is Model::model_guid: Option<String> (JSON key model_guid); header_info returns an optional GUID.
  • Model::scenes is Vec<Scene>.
  • New public fields: Instance and PlacedInstance carry pid and slot, GeometryRun gains sections, Scene gains hidden_layers, Guide gains def_index.