The Elm Story schema defines storyworld content structure. When exporting, all storyworld content is included, creating a complete, human-readable and transportable snapshot that you can use with version control and 3rd party tools.
Since 0.1.3, Elm Story has supported automatic migration, updating your imported data to use the latest features. ES also validates your imports to our schema, so you don’t have to worry about IO degradation with imports/exports.
Providing a bit of a walkthrough to show how your content maps.
0.6 marks the first ES release to support binary assets. So, let’s say you are defining a character’s personality. For masks (portraits), you select an image and crop to our 5:4 default.
In the next screenshot, masks have been defined for NEUTRAL (default) and TENSE.
When exporting your storyworld, you will be prompted to select a folder. Elm Story then gathers everything up and saves to a nested folder, using convention {storyworld-title}_{version}_{timestamp}
. In this case: darker-materials_0.0.1_1638575653638
.
Elm Story will then open the folder to show you the result.
Same process for PWA export:
JSON export:
Contents of assets
folder:
Binary assets are assigned a UUID, which I’ll cover toward the end of this post.
When importing, you would select either the storyworld folder or nested JSON file. Your content is then validated and copied and will hydrate the internal database. Assets are copied to Elm Story’s app folder.
To show how this maps, take a look at the following passage
(changing to event
in 0.6) from Amber Shores.
I export and open the JSON, searching for the lamp is on
.
Passage (changing element type term to Event in 0.6)
"ca122de2-5736-43cc-86fd-5f23c575e8a1": {
"choices": [
"62895cad-0dca-417a-9487-ca786565d80d"
],
"content": "[{\"type\":\"paragraph\",\"children\":[{\"text\":\"The lamp is on, dimly glowing with red haze.\"}]},{\"type\":\"paragraph\",\"children\":[{\"text\":\"Under the stained glass shade hangs a tattered, gold chain.\"}]}]",
"editor": {
"componentEditorPosX": 878.8715500354701,
"componentEditorPosY": 469.6388451062143
},
"gameOver": false,
"id": "ca122de2-5736-43cc-86fd-5f23c575e8a1",
"sceneId": "fa2ecaf4-7746-4cdf-9bc8-0992738a7db3",
"tags": [],
"title": "Examining the lamp",
"type": "CHOICE",
"updated": 1635994554460
}
Please note the content
property. As mentioned in a previous post, Elm Story has a deep writing tool that currently supports paragraphs
, but will eventually support all kinds of markup and special object types like images, character references (@), headings, custom styles and more.
Now, if I want to find the scene (parent) and choice (child) defined in this passage, I can search the JSON by UUIDs.
Scene
"fa2ecaf4-7746-4cdf-9bc8-0992738a7db3": {
"children": [
[
"PASSAGE",
"646575da-18f4-434b-8270-cfa41a73e290"
],
[
"PASSAGE",
"ca122de2-5736-43cc-86fd-5f23c575e8a1"
],
[
"PASSAGE",
"28a637df-584f-4ff7-9969-5e633da5d6e8"
],
[
"PASSAGE",
"09a1dab3-b83d-405e-9521-0f5336ce73b2"
],
[
"PASSAGE",
"a623eae4-7624-40aa-879b-60b2bb731f5e"
],
[
"PASSAGE",
"0ebfa65d-bfa6-45ed-abbe-55d457bc76bf"
],
[
"PASSAGE",
"f38457e7-2800-46f9-9d65-b38130221563"
],
[
"PASSAGE",
"d36396ed-7a5c-451a-b020-b11fdd2abba8"
],
[
"PASSAGE",
"569d12c3-7050-49e0-891e-9fde24167822"
]
],
"editor": {
"componentEditorTransformX": -1748.52667890061,
"componentEditorTransformY": -429.204747466243,
"componentEditorTransformZoom": 1.3195079107728946
},
"id": "fa2ecaf4-7746-4cdf-9bc8-0992738a7db3",
"jumps": [
"109af87a-6617-4fa5-bb7f-cddd36b6fabe"
],
"parent": [
"FOLDER",
"58ee805c-2f58-4614-bfbc-c7d123272517"
],
"tags": [],
"title": "The Room",
"updated": 1636067636434
}
Choice
"62895cad-0dca-417a-9487-ca786565d80d": {
"id": "62895cad-0dca-417a-9487-ca786565d80d",
"passageId": "ca122de2-5736-43cc-86fd-5f23c575e8a1",
"tags": [],
"title": "Pull chain",
"updated": 1632154503352
}
Anything related to Elm Story tool configuration, in the context of your storyworlds, is nested to an editor
object. This is used to track things like where a node is positioned or a scene’s zoom level.
This structure makes it easy to filter ES-specific configuration properties when parsing your storyworld’s content (3rd party tool), but also persist this configuration for when you would like to import and keep your e.g. node positions intact.
In 0.6, the editor is renamed to composer, so the editor
object is renamed composer
. componentEditor*
properties (in the context of scene and event) are renamed sceneMap*
, so componentEditorTransformZoom
is now sceneMapTransformZoom
.
Back to characters and binary assets!
I’ve exported a demo game, Darker Materials, as JSON.
Character
"characters": {
"48ed0760-72df-4490-8faa-8f9e4e6373f4": {
"id": "48ed0760-72df-4490-8faa-8f9e4e6373f4",
"masks": [
{
"type": "NEUTRAL",
"active": true,
"assetId": "cf66f8ea-5643-4362-a334-8cc10ddbdaba"
},
{
"type": "TENSE",
"active": true,
"assetId": "c3827dbd-95a8-42e0-ab11-7d8f6f14944d"
}
],
"refs": [
[
"d2029cac-6b85-4014-89cb-2245bc21bdf3",
"HE"
],
[
"386a4f1f-e421-4f87-a748-2773ef6d7580",
"HIM"
],
[
"47cbea81-6bf9-4bf4-bc48-d60581896763",
"IOREK"
],
[
"1b626d0f-4520-4236-8b05-7acc0b9ed76d",
"KING"
]
],
"tags": [],
"title": "Iorek Byrnison",
"updated": 1638588863786
}
}
If I wanted to find the asset for the TENSE
mask, I would look under the exported (as JSON) storyworld > assets
and search c3827dbd-95a8-42e0-ab11-7d8f6f14944d
…
I hope this helps!