Commit Graph

65 Commits

Author SHA1 Message Date
03cd1d4ca0 Binary format for chunks in zipfiles 2023-02-18 12:45:36 -08:00
31097881ff Finalize Non-square Doodads
* Fix display bug with rectangular doodads scrolling off screen.
* The default Author of new files will be your registration name, if available
  before using your $USER name.
2023-02-17 21:09:11 -08:00
ddcad27485 WIP: Chunker size to uint8 and Rectangular Doodads
Convert the Chunker size to a uint8 so chunk sizes are limited to 255px. This
means that inside of a chunk, uint8's can track the relative pixel coordinates
and result in a great memory savings since all of these uint8's are currently
64-bits wide apiece.

WIP on rectangular shaped doodads:
* You can create such a doodad in the editor and draw it normally.
* It doesn't draw the right size when dragged into your level however:
  - In uix.Actor.Size() it gets a rect of the doodad's square Chunker size,
    instead of getting the proper doodad.Size rect.
  - If you give it the doodad.Size rect, it draws the Canvas size correctly
    instead of a square - the full drawing appears and in gameplay its hitbox
    (assuming the same large rectangle size) works correctly in-game.
  - But, the doodad has scrolling issues when it gets to the top or left edge
    of the screen! This old gnarly bug has come back. For some reason square
    canvas doodads draw correctly but rectangular ones have the drawing scroll
    just a bit - how far it scrolls is proportional to how big the doodad is,
    with the Start Flag only scrolling a few pixels before it stops.
2023-02-16 21:47:18 -08:00
701073cecc Doodad/Actor Runtime Options
* Add "Options" support for Doodads: these allow for individual Actor instances
  on your level to customize properties about the doodad. They're like "Tags"
  except the player can customize them on a per-actor basis.
* Doodad Editor: you can specify the Options in the Doodad Properties window.
* Level Editor: when the Actor Tool is selected, on mouse-over of an actor,
  clicking on the gear icon will open a new "Actor Properties" window which
  shows metadata (title, author, ID, position) and an Options tab to configure
  the actor's options.

Updates to the scripting API:

* Self.Options() returns a list of option names defined on the Doodad.
* Self.GetOption(name) returns the value for the named option, or nil if
  neither the actor nor its doodad have the option defined. The return type
  will be correctly a string, boolean or integer type.

Updates to the doodad command-line tool:

* `doodad show` will print the Options on a .doodad file and, when showing a
  .level file with --actors, prints any customized Options with the actors.
* `doodad edit-doodad` adds a --option parameter to define options.

Options added to the game's built-in doodads:

* Warp Doors: "locked (exit only)" will make it so the door can not be opened
  by the player, giving the "locked" message (as if it had no linked door),
  but the player may still exit from the door if sent by another warp door.
* Electric Door & Electric Trapdoor: "opened" can make the door be opened by
  default when the level begins instead of closed. A switch or a button that
  removes power will close the door as normal.
* Colored Doors & Small Key Door: "unlocked" will make the door unlocked at
  level start, not requiring a key to open it.
* Colored Keys & Small Key: "has gravity" will make the key subject to gravity
  and set its Mobile flag so that if it falls onto a button, it will activate.
* Gemstones: they had gravity by default; you can now uncheck "has gravity" to
  remove their Gravity and IsMobile status.
* Gemstone Totems: "has gemstone" will set the totem to its unlocked status by
  default with the gemstone inserted. No power signal will be emitted; it is
  cosmetic only.
* Fire Region: "name" can let you set a name for the fire region similarly to
  names for fire pixels: "Watch out for ${name}!"
* Invisible Warp Door: "locked (exit only)" added as well.
2022-10-09 17:41:24 -07:00
cd103f06c7 Touchscreen fixes 2022-09-24 19:05:42 -07:00
546b5705db Detect touchscreen and tweak some behaviors 2022-09-24 17:45:54 -07:00
ec0b5ba6ca Rename Go module 2022-09-24 15:17:25 -07:00
d7f247e4cc Fix doodad tool --tag property 2022-05-08 10:58:53 -07:00
4efa8d00fc Fancy Mouse Cursors
The gamepad mouse cursor has become THE mouse cursor. It is always visible and your
real cursor is hidden, and this way the game can swap out other cursors for certain
scenarios:

* The Pencil Tool in the editor will use a pencil cursor over the level canvas.
* The Flood Tool has a custom Flood cursor so you don't forget it's selected!

Other improvements:

* The Palette buttons in the editor now render using their swatch's pattern
  instead of only using its color.
* If you have an ultra HD monitor and open a Bounded level in the editor which
  is too small to fill your screen, the editor canvas limits its size to fit
  the level (preferable over showing parts of the level you can't actually play
  as it's out of bounds).
* The "brush size" box is only drawn around the cursor when a relevant tool is
  selected (Pencil, Line, Rect, Ellipse, Eraser)
2022-05-04 22:38:26 -07:00
9b75f1b039 Spit and polish
* New built-in wallpaper: "Dotted paper (dark)" is a dark-themed wallpaper.
* New built-in palette: "Neon Bright" with bright colors for dark levels.
* New cheat: "warp whistle" to automatically win the level.
* In case the user has a VERY LARGE screen resolution bigger than the full
  bounds of a Bounded level, the Play Scene will cap the size and center
  the level canvas onto the window. This is preferable to being able to see
  beyond the level's boundaries and hitting an invisible wall in-game.
* Make the titlescreen Lazy Scroll work on unbounded levels. It can't bounce
  off scroll boundaries but it will reverse course if it reaches the level's
  furthest limits.
* Bugfix: characters' white eyes were transparent in-game. Multiple culprits
  from the `doodad convert` tool defaulting the chroma key to white, to the
  SDL2 textures considering white to be transparent. For the latter, the game
  offsets the color by -1 blue.
2022-05-03 21:15:39 -07:00
75fa0c7e56 Stability and Bugfixes
* Editor: Auto-save on a background goroutine so you don't randomly freeze
  the editor up during.
* Fix actor linking issues when you drag and re-place a linked doodad: the
  level was too eagerly calling PruneLinks() whenever a doodad was 'destroyed'
  (such as the one just picked up) breaking half of the link connection.
* Chunk unloader: do not unload a chunk that has been modified (Set or Delete
  called on), keep them in memory until the next ZIP file save to flush them
  out to disk.
* Link Tool: if you clicked an actor and don't want to connect a link, click
  the first actor again to de-select it.

Updates to the `doodad` tool:

* `doodad edit-level --resize <int>` can re-chunk a level to use a different
  chunk size than the default 128. Large chunk sizes 512+ lead to performance
  problems.
2022-05-02 20:35:53 -07:00
93623e4e8a Zipfiles as File Format for Levels and Doodads
Especially to further optimize memory for large levels, Levels and
Doodads can now read and write to a ZIP file format on disk with
chunks in external files within the zip.

Existing doodads and levels can still load as normal, and will be
converted into ZIP files on the next save:

* The Chunker.ChunkMap which used to hold ALL chunks in the main json/gz
  file, now becomes the cache of "hot chunks" loaded from ZIP. If there is
  a ZIP file, chunks not accessed recently are flushed from the ChunkMap
  to save on memory.
* During save, the ChunkMap is flushed to ZIP along with any non-loaded
  chunks from a previous zipfile. So legacy levels "just work" when
  saving, and levels loaded FROM Zip will manage their ChunkMap hot
  memory more carefully.

Memory savings observed on "Azulian Tag - Forest.level":

* Before: 1716 MB was loaded from the old level format into RAM along
  with a slow load screen.
* After: only 243 MB memory was used by the game and it loaded with
  a VERY FAST load screen.

Updates to the F3 Debug Overlay:

* "Chunks: 20 in 45 out 20 cached" shows the count of chunks inside the
  viewport (having bitmaps and textures loaded) vs. chunks outside which
  have their textures freed (but data kept), and the number of chunks
  currently hot cached in the ChunkMap.

The `doodad` tool has new commands to "touch" your existing levels
and doodads, to upgrade them to the new format (or you can simply
open and re-save them in-game):

    doodad edit-level --touch ./example.level
    doodad edit-doodad --touch ./example.doodad

The output from that and `doodad show` should say "File format: zipfile"
in the headers section.

To do:

* File attachments should also go in as ZIP files, e.g. wallpapers
2022-04-29 20:34:59 -07:00
9cdc7260bb Prepare v0.12.1 for release 2022-04-16 17:50:40 -07:00
ba373553cb Prepare v0.12.0 for release 2022-03-27 14:23:25 -07:00
4de0126b19 Game Controller Support
Adds support for Xbox and Nintendo style game controllers. The gamepad
controls are documented on the README and in the game's Settings window.

The buttons are not customizable yet, except that the player can choose
between two button styles:

* X Style (default): "A" button is on the bottom and "B" on the right.
* N Style: swaps the A/B and the X/Y buttons to use a Nintendo-style
  layout instead of an Xbox-style.
2022-02-19 18:31:22 -08:00
cbd7816fdf Easter Egg: RiveScript Chatbot
The Default handler of the developer command shell now calls out to
RiveScript to match the user's message to a friendly reply. If
RiveScript returns NoReplyMatched then give the "command not found"
error.
2022-01-08 19:21:08 -08:00
d16a8657aa Window Icon, UI Polish
* SDL2 builds of the game now set their app window icon.
* Create/Edit Level window is updated to show a tabbed UI to create a
  new Level or a new Doodad. The dedicated main menu button to create a
  new doodad (which immediately prompted for its size) is replaced by
  this new tab's UI.
* Edit Drawing/Play Level window is more responsive to smaller screen
  sizes by drawing fewer columns of filenames.
* Bugfix: the Alert and Confirm modals always re-center themselves on
  screen, especially to adapt between Portrait or Landscape mode on a
  mobile device.
2021-12-30 16:31:45 -08:00
a75b7208ca Doodad Tool: Levelpacks
Adds `doodad levelpack create` and `doodad levelpack show` commands to
the CLI tool to create levelpacks.

A levelpack is a ZIP file containing a descriptive index.json and
directories for levels and doodads.
2021-12-23 19:15:32 -08:00
0ec259b171 Crosshair Option + Doodad Editor crash fix
* The level scroll logic was getting a null pointer crash if you open a
  doodad rather than a level file.
* Add a crosshair option to the level editor, configurable in the Game
  Settings window.
2021-10-11 15:57:33 -07:00
e80a3f0446 Various minor tweaks and changes
* Recolor some of the region doodads
* Add command: `doodad edit-level --remove-actor` to remove actors from
  your level.
* Tweak the player jump velocity from playtesting levels.
2021-10-07 20:50:24 -07:00
0a8bce708e Actor Zoom + Experimental Settings GUI
Improvements to the Zoom feature:
* Actor position and size within your level scales up and down
  appropriately. The canvas size of the actor is scaled and its canvas
  is told the Zoom number of the parent so it will render its own
  graphic scaled correctly too.

Other features:
* "Experimental" tab added to the Settings window as a UI version of the
  --experimental CLI option. The option saves persistently to disk.
* The "Replace Palette" experimental feature now works better. Debating
  whether it's a useful feature to even have.
2021-09-11 21:18:22 -07:00
f446ed9130 Prepare v0.8.0 for release 2021-09-03 21:35:12 -07:00
3486050702 Go 1.16 embed instead of go-bindata
* Migrate off go-bindata to embed built-in fonts, levels and doodads in
  favor of Go 1.16 native embed functionality.
* `make bindata` prints a deprecation warning to not break older build
  scripts
* Removes all references of bindata from the program
2021-07-13 18:04:25 -07:00
864156da53 Settings Window + Bugfix
* Added a Settings window for game options, such as enabling the
  horizontal toolbars in Edit Mode. The Settings window also has a
  Controls tab showing the gameplay buttons and keyboard shortcuts.
* The Settings window is available as a button on the home screen OR
  from the Edit->Settings menu in the EditScene.
* Bugfix: using WASD to move the player character now works better and
  is considered by the game to be identical to the arrow key inputs. Boy
  now updates his animation based on these keys, and they register as
  boolean on/off keys instead of affected by key-repeat.
* Refactor the boolProps: they are all part of usercfg now, and if you
  run e.g. "boolProp show-all-doodads true" and then cause the user
  settings to save to disk, that boolProp will be permanently enabled
  until turned off again.
2021-06-19 22:14:41 -07:00
0449737607 License Key Registration with ECDSA JWT Tokens
* New command-line tool: doodle-admin for signing license keys for
  users. Includes functions to initialize a keypair, sign license keys
  and validate existing keys.
* The Main Menu screen shows a blue "Register Game" button in the bottom
  right corner of the screen, for unregistered users only.
* In Edit Mode, there is a "Help -> Register" menu item that opens the
  License Window.
* The License UI Window lets the user select the license.key file to
  register the game with. If registered, a copy of the key is placed in
  Doodle's profile directory and the licensee name/email is shown in the
  License UI window.
* Unregistered games will show the word "(shareware)" next to the title
  screen version number and Edit Mode status bar.
* No restrictions are yet placed on free versions of the game.
2021-06-16 21:56:30 -07:00
d6f86487f5 Horizontal Toolbars Option for Editor Mode
On small screen sizes like the Pinephone, the toolbars in the Level
Editor are best made horizontal across the top and bottom of the screen
leaving more room for the drawing.

Enable it with a boolProp for now, and then reopen the level editor:

    boolProp horizontalToolbars true

When launching `doodle -w mobile` it will automatically enable this
option.
2021-06-13 21:23:26 -07:00
e8388fafad Title Screen: Lazily scroll the demo level
Adds a lazy scroll algorithm that basically:
- Zigzags right/down a certain distance, then up again
- Then enters a bounce phase where it bounces off the level
  boundaries like a screensaver.

Arrow keys can still scroll the level manually, but the
automated scroll takes over otherwise.
2021-06-08 21:12:30 -07:00
640e75ba4d Custom Wallpapers for Levels
* You can now browse for a custom wallpaper image to use with your
  levels. A platform-native file picker dialog is used (no WASM support)
* In the New/Edit Level Properties dialog, the Wallpaper drop-down
  includes an option to browse for a custom map.
* When editing an existing level: the wallpaper takes effect immediately
  in your level once the file is picked. For NEW levels, the wallpaper
  will appear once the "Continue" button is pressed.
* All common image types supported: png, jpeg, gif.
* The wallpaper is embedded in the level using the filepath
  "assets/wallpapers/custom.b64img" as a Base64-encoded blob of the
  image data.
* The `doodad show` command will list the names and sizes of files
  embedded in levels. `doodad show --attachment <name>` will get an
  attachment and print it to the console window.
* To extract a wallpaper image from a level:
  `doodad show -a assets/wallpapers/custom.b64img | base64 -d > out.png`
2021-06-06 18:59:04 -07:00
1f274e0ca6 Changelog and Prepare v0.5.0 for Release 2021-03-31 19:16:33 -07:00
c78cd38c1d Add chdir option for Flatpak
* The --chdir CLI option to doodle will set a working directory for the
  game to switch to on startup. Flatpak builds place the files at
  /app/share/doodle where the ./rtp and ./guidebook files are relative
  to and this allows the game to find its sound effects and such.
2020-12-28 18:32:55 -08:00
6e40d58010 WIP Zoom Tool
* Added Feature Flag support, run doodle with --experimental to enable
  all flags. Eraser Tool is behind a feature flag now.
* + and - on the top row of keyboard keys will zoom the drawing in and
  out in Edit Mode. The wallpaper zooms nicely enough, but level
  chunkers need work.
* A View menu is added with Zoom in/out, reset zoom, and scroll to
  origin options. The whole menu is behind the Zoom feature flag.
* Update README with lots of details for fun debug mode options to play
  around with.
2020-11-19 20:09:15 -08:00
bc02f2c685 Convert to use Go modules 2020-11-15 15:20:15 -08:00
47cca8c7c6 Palette Editor and Doodad Dropper Windows
* Start the program window maximized with the `-w maximized` CLI option.
* Move the Doodad Palette off the right-side dock of the Editor Scene and
  into its own pop-up window: the DoodadDropper.
* Shrink the width of the Color Palette panel and show only the colors in
  the buttons. The name of the swatch is available in the mouse-over tooltip.
* Added an "Edit" button to the Color Palette. It opens a Palette Editor
  window where you can rename, change colors and attributes of existing colors
  OR insert new colors into your palette. (Deleting colors not yet supported).
* level.Chunker gets a Redraw method: invalidates all cached textures of all
  chunks forcing the level to redraw itself, possibly with an updated palette.
2020-07-09 19:38:37 -07:00
5f75168235 Command-line flag for window resolution
* Added a --window flag to the game executable to specify the startup
  window resolution. Either specify an exact size (e.g. 1024x768) or a
  special keyword "desktop", "mobile" or "landscape"
* Default size is "desktop" or 1024x768
* Mobile simulates a smartphone form factor of 375x812
* Landscape is mobile but flipped horizontally.
* Doodle UX isn't great on mobile but this is a step towards working on
  mobile friendly UI
2020-06-17 18:21:15 -07:00
8964322f4e Fix doodad edit-doodad args 2020-06-05 00:26:48 -07:00
eae7258ce1 Modernize usage of urfave/cli 2020-06-04 23:11:03 -07:00
27896a9253 Add Initial Sound Effects
Adds support for sound effects in Doodle and configures some for various
doodads to start out with:

* Buttons and Switches: "Clicked down" and "clicked up" sounds.
* Colored Doors: an "unlocked" sound and a "door opened" sound.
* Electric Door: sci-fi sounds when opening and closing.
* Keys: sound effect for collecting keys.

JavaScript API for Doodads adds a global function `Sound.Play(filename)`
to play sounds. All sounds in the `rtp/sfx/` folder are pre-loaded on
startup for efficient use in the app. Otherwise sounds are lazy-loaded
on first playback.
2020-05-22 20:07:48 -07:00
38614ee280 Tighten Doodad JavaScript API, User Documentation
* Tightens up the surface area of API methods available to the
  JavaScript VMs for doodads. Variables and functions are carefully
  passed in one-by-one so the doodad script can only access intended
  functions and not snoop on undocumented APIs.
* Wrote tons of user documentation for Doodad Scripts: documented the
  full surface area of the exposed JavaScript API now that the surface
  area is known and limited.
* Early WIP code for the Campaign JSON
2020-04-21 23:50:45 -07:00
b4922edf5d Doodad Tool: Add Tag Support for edit-doodad
* The `doodad edit-doodad` command now allows setting custom key/value
  tags in doodad files, for extra data storage useful to their scripts.
* Colored keys and doors now store a `color` tag with the appropriate
  color so that their scripts don't have to parse their Title to find
  that information.
* Trapdoors now store a `direction` tag to hold the direction the door
  is facing.
2020-01-02 22:12:20 -08:00
8965a7d86a Doodads: Crumbly Floor, Start Flag & State Blocks
Add new doodads:

* Start Flag: place this in a level to set the spawn point of the player
  character. If no flag is found, the player spawns at 0,0 in the top
  corner of the map. Only use one Start Flag per level, otherwise the
  player will randomly spawn at one of them.
* Crumbly Floor: a solid floor that begins to shake and then fall apart
  after a moment when a mobile character steps on it. The floor respawns
  after 5 seconds.
* State Blocks: blue and orange blocks that toggle between solid and
  pass-thru whenever a State Button is activated.
* State Button: a solid "ON/OFF" block that toggles State Blocks back
  and forth when touched. Only activates if touched on the side or bottom;
  acts as a solid floor when walked on from the top.

New features for doodad scripts:

* Actor scripts: call SetMobile(true) to mark an actor as a mobile mob
  (i.e. player character or enemy). Other doodads can check if the actor
  colliding with them IsMobile so they don't activate if placed too close
  to other (non-mobile) doodads in a level. The Blue and Red Azulians
  are the only mobile characters so far.
* Message.Broadcast allows sending a pub/sub message out to ALL doodads
  in the level, instead of only to linked doodads as Message.Publish does.
  This is used for the State Blocks to globally communicate on/off status
  without needing to link them all together manually.
2019-12-30 18:13:28 -08:00
ea0b41a781 Cut lib/render into its own package, change all imports 2019-12-22 18:21:58 -08:00
154fc6c9cb Update Doodad build-scripts to tag extra data
* The Blue Azulian marks its doodad file as Hidden.
* All Doodads are write locked after generation and tagged with common
  author value.
2019-07-06 23:50:38 -07:00
fd649b7ab1 Doodad CLI Tool Features; Write Lock and Hidden
* The `doodad` CLI tool got a lot of new commands:
  * `doodad show` to verbosely print details about Levels and Doodads.
  * `edit-level` and `edit-doodad` to update details about Levels and
    Doodads, such as their Title, Author, page type and size, etc.
* Doodads gain a `Hidden bool` that hides them from the palette in
  Editor Mode. The player character (Blue Azulian) is Hidden.
* Add some boolProps to the balance/ package and made a dynamic system
  to easily configure these with the in-game dev console.
  * Command: `boolProp list` returns available balance.boolProps
  * `boolProp <name>` returns the current value.
  * `boolProp <name> <true or false>` sets the value.
* The new boolProps are:
  * showAllDoodads: enable Hidden doodads on the palette UI (NOTE:
    reload the editor to take effect)
  * writeLockOverride: edit files that are write locked anyway
  * prettyJSON: pretty-format the JSON files saved by the game.
2019-07-06 23:28:11 -07:00
3d08291bc5 Demo Running Level as Title Screen Wallpaper
* Load SDL2 fonts from go-bindata storage so we don't have to ship
  external font files on disk.
* Dedupe names of doodads so we don't show double on the front-end
  (go-bindata bundled doodads + those on local filesystem)
* Use go-bindata for accessing wallpaper images.
* Better flashed messages walking you through the Link Tool.
* Stylize the title screen (MainScene) by rendering a live example level
  as the background wallpaper, with mobile doodads in motion.
2019-06-27 22:59:36 -07:00
1150d6d3e9 Add Branding Module for Centralized Game Info
* Moves the game's Title, Summary and Version into pkg/branding where it
  is centrally controlled.
2019-06-23 17:52:48 -07:00
61af068b80 Load Balance Collision and Actor Loop Across CPU Cores
* Add sync.WaitGroup to some parts of the level collision detection
  function and Canvas.Loop() to speed up the frame rate by load
  balancing some work in parallel across multiple cores.
* Improves FPS from 30 to 55+ even for busy scenes with lots of mobile
  enemies walking around.
* Before the level collision optimization, framerate would sometimes dip
  to 30 FPS simply to move the player character on a completely blank
  map!
2019-05-06 17:06:40 -07:00
a73dec9f31 Doodad Animations Managed In-Engine
* Add animation support for Doodad actors (Play Mode) into the core
  engine, so that the Doodad script can register named animations and
  play them without managing all the details themselves.
  * Doodad API functions on Self: AddAnimation, PlayAnimation,
    StopAnimation, IsAnimating
* CLI: the `doodad convert` command will name each layer after the
  filename used as the input image.
* CLI: fix the `doodad convert` command creating duplicate Palette
  colors when converting a series of input images into a Doodad.
2019-05-06 15:30:43 -07:00
693664db6c Shareware Build Flags
* Build the app with -tags="shareware" to compile the free/shareware
  build of the game.
* `make build-free` compiles both binaries to the bin/ folder in
  shareware mode.
* The constant balance.FreeVersion is true in the shareware build and
  all functionality related to the Doodad Editor UI mode is disabled
  in this build mode.
2019-04-19 17:23:37 -07:00
258b2eb285 Script Timers, Multiple Doodad Frames
* CLI: fix the `doodad convert` command to share the same Palette when
  converting each frame (layer) of a doodad so subsequent layers find
  the correct color swatches for serialization.
* Scripting: add timers and intervals to Doodad scripts to allow them to
  animate themselves or add delayed callbacks. The timers have the same
  API as a web browser: setTimeout(), setInterval(), clearTimeout(),
  clearInterval().
* Add support for uix.Actor to change its currently rendered layer in
  the level. For example a Button Doodad can set its image to Layer 1
  (pressed) when touched by the player, and Trapdoors can cycle through
  their layers to animate opening and closing.
  * Usage from a Doodad script: Self.ShowLayer(1)
* Default Doodads: added scripts for all Buttons, Doors, Keys and the
  Trapdoor to run their various animations when touched (in the case of
  Keys, destroy themselves when touched, because there is no player
  inventory yet)
2019-04-18 18:15:05 -07:00
81cb3bd617 1st Round of Doodad Sprites + Improve Doodad Tool
* Improve the `doodad convert` command to convert a series of input
  images into multiple Frames of a Doodad:
  `doodad convert frame1.png frame2.png frameN.png output.doodad`
* Add the initial round of dev-asset sprites for the default Doodads:
  * Button, Button-TypeB and Sticky Button
  * Red, Blue, Green and Yellow Locked Doors and Keys
  * Electric Door
  * Trapdoor Down
* Add dev-assets/palette.json that defines our default doodad color
  palette. Eventually the JSON will be used by the `doodad` tool to give
  the layers meaningful names.
2019-04-17 00:02:41 -07:00