diff --git a/source/presentation/4.0/index.md b/source/presentation/4.0/index.md
index 65bd92298..634925340 100644
--- a/source/presentation/4.0/index.md
+++ b/source/presentation/4.0/index.md
@@ -35,6 +35,25 @@ hero:
image: ''
---
+
+
# Status of this Document
{:.no_toc}
__This Version:__ {{ page.major }}.{{ page.minor }}.{{ page.patch }}{% if page.pre != 'final' %}-{{ page.pre }}{% endif %}
@@ -325,50 +344,25 @@ The fragment example above can be expressed using a Specific Resource:
}
```
+## Navigational Resources
-## Supporting Resources
-
-Constructs from the domain of 3D graphics are expressed in IIIF as Resources. They are associated with Scenes via Painting Annotations in the same manner as Content Resources. They aid in or enhance the rendering of Content Resources, especially in Scenes.
-
-### Cameras
-
-A Camera provides a view of a region of the Scene's space from a particular position within the Scene; the client constructs a viewport into the Scene and uses the view of one or more Cameras to render that region. The size and aspect ratio of the viewport is client and device dependent.
-
-There are two types of Camera, `PerspectiveCamera` and `OrthographicCamera`. The first Camera defined and not hidden in a Scene is the default Camera used to display Scene contents. If the Scene does not have any Cameras defined within it, then the client provides a default Camera. The type, properties and position of this default camera are client-dependent.
-
-
-### Lights
-
-There are four types of Light: AmbientLight, DirectionalLight, PointLight and SpotLight. They have a `color` and an `intensity`. SpotLight has an additional property of `angle` that determines the spread of its light cone.
-
-If the Scene has no Lights, then the client provides its own lighting as it sees fit.
-
-
-### Audio Emitters
-
-There are three types of Audio emitter: AmbientAudio, PointAudio and SpotAudio. They have a `source` (an audio Content Resource) and a `volume`.
-
-### Transforms
-
-When painting resources into Scenes, it is often necessary to resize, rotate or move them relative to the coordinate space of the Scene. These operations are specified using three Transforms: ScaleTransform, RotateTransform and TranslateTransform. Each Transform has three properties, `x`, `y` and `z` which determine how the Transform affects that axis in the local coordinate space.
+### Collection
-Transforms are added to a SpecificResource using the `transform` property, and there may be more than one applied when adding a model to a Scene. Different orders of the same set of transforms can have different results, so attention must be paid when creating the array and when processing it.
+IIIF Collections are ordered lists of Manifests, Collections, and/or Specific Resources. Collections allow these resources to be grouped in a hierarchical structure for navigation and other purposes.
-### Agent
+:eyes:
-Any resource can have a `provider` property which a client can display to the user. This typically tells the user who the publisher is and how they might be contacted. The value of this property is an [Agent](model/#agent).
+### Range
-### Service
+IIIF Ranges are used to represent structure _WITHIN_ a Manifest beyond the default order of the Containers in the `items` property. Example uses include newspaper sections or articles, chapters within a book for a table of contents, or movements within a piece of music. Ranges can include Containers, parts of Containers via Specific Resources or fragment URIs, or other Ranges, creating a tree structure like a table of contents. The typical intent of adding a Range to the Manifest is to allow the client to display a linear or hierarchical navigation interface to enable the user to quickly move through the object's content.
-A Service is a software application that a client might interact with to gain additional information or functionality. The IIIF Image API is an example of a Service.
+:eyes:
-### Unit Value
-To express a numerical measure in some particular unit, we use a UnitValue resource that has `value` and `unit` properties. For example a Scene coordinate system might be in meters.
# Image Content
-## Use Case 1: Artwork
+## Use Case 1: Artwork with deep zoom
This example is a Manifest with one Canvas, representing an artwork. The content resource, a JPEG image of the artwork, is associated with the Canvas via a Painting Annotation.
@@ -376,7 +370,7 @@ The unit integer coordinates of the Canvas (12000 x 9000) are not the same as th
The example demonstrates the use of the common descriptive properties `label` for the title of the artwork, `metadata` for additional information to display to the user, `summary` for a brief description of the artwork, `rights` to assert a rights statement or license from a controlled vocabulary, `homepage` to link to the artwork's specific web page, `thumbnail` to provide a small image to stand for the Manifest, and `provider` to give information about the publisher of the Manifest.
-```json
+```jsonc
{
"@context": "http://iiif.io/api/presentation/4/context.json",
"id": "https://iiif.io/api/cookbook/recipe/0001-mvm-image/manifest.json",
@@ -458,7 +452,14 @@ The example demonstrates the use of the common descriptive properties `label` fo
"type": "Image",
"format": "image/jpeg",
"width": 4000,
- "height": 3000
+ "height": 3000,
+ "service": [
+ {
+ "id": "https://iiif.io/api/image/efjfpewjfpewjfoiewjf",
+ "type": "imageService3",
+ // etc
+ }
+ ]
},
"target": "https://example.org/iiif/presentation/examples/manifest-with-containers/canvas"
}
@@ -479,6 +480,8 @@ The example demonstrates the use of the common descriptive properties `label` fo
* The Painting Annotation is a member of the `items` property of an Annotation Page. While in this case there is only one Annotation Page and one Annotation, the mechanism is needed for consistency when there are multiple Annotation Pages, and it allows for Annotation Pages in general to be separate resources on the web.
* The `metadata` label and value pairs are for display to the user rather than for machines to interpret.
* The `rights` property is always a single string value which is a URI.
+* Any resource can have a `provider` property which a client can display to the user. This typically tells the user who the publisher is and how they might be contacted. The value of this property is an [Agent](model/#agent).
+* A Service is a software application that a client might interact with to gain additional information or functionality. The IIIF Image API in this example ia a Service, which provides deep zoom functionality. Images in IIIF do not have to have Image Services - the following examples don't.
{: .note}
!!! warning TODO: The above should be a green class rgb(244,252,239) to distinguish from properties
@@ -620,9 +623,187 @@ Properties: [behavior](#model/behavior), [viewingDirection](#model/viewingDirect
{: .note}
+
+## Use Case 3: Periodical
+
+This example demonstrates the use of IIIF Collections to group Manifests into a hierarchy. In this case, there is a Collection for a publishing run of the _The Tombstone Epitaph_ from 1880 to 1920. This contains 41 child Collections each representing a year's worth of issues. The parent Collection and each of its child Collections use the `behavior` "multi-part" to signal that the Collections and their Manifests are part of a logical whole or contiguous set. Each of the year Collections has one Manifest for each issue of the newspaper.
+
+The top level Collection has a `navPlace` property that could be used on a "Newspapers of America" map to allow users to view newspapers by location. Each Manifest has a `navDate` property that could be used to plot the issues on a calendar-style user interface. Within each Manifest, the `structures` property provides Ranges which are used to identify individual sections of the Newspaper, and individual stories within the sections, which may be spread across multiple columns and pages. Each story's Range includes the `supplementary` property to link to an Annotation Collection that provides the text of the story.
+
+IIIF Collection with `behavior` "multi-part" that contains the individual "multi-part" Collections for each year/volume:
+
+```json
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "https://example.org/iiif/periodical/collection.json",
+ "type": "Collection",
+ "label": { "en": [ "The Tombstone Epitaph (1880-1920)" ] },
+ "behavior": [ "multi-part" ],
+ "navPlace": {
+ "id": "https://example.org/iiif/periodical/collection/place/1",
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "id": "https://example.org/iiif/periodical/collection/feature/1",
+ "type": "Feature",
+ "properties": {
+ "label": { "en": ["Tombstone, Cochise County, Arizona"] }
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [31.715940, −110.064827]
+ }
+ }
+ ]
+ },
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/v1.json",
+ "type": "Collection",
+ "label": { "en": [ "The Tombstone Epitaph, 1880" ] }
+ },
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/v2.json",
+ "type": "Collection",
+ "label": { "en": [ "The Tombstone Epitaph, 1881" ] }
+ },
+ // Additional multi-part collections for each year/volume
+ ]
+}
+```
+IIIF Collection with `behavior` "multi-part" for the second volume (1881), with individual Manifests for each issue.
+
+```json
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "https://example.org/iiif/periodical/multi-part-collection/v1.json",
+ "type": "Collection",
+ "label": { "en": [ "The Tombstone Epitaph, 1881" ] },
+ "behavior": [ "multi-part" ],
+ "items": [
+ // Previous issues
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/issue1.json",
+ "type": "Manifest",
+ "label": { "en": [ "October 27, 1881" ] }
+ },
+ // Subsequent issues
+ ]
+}
+```
+
+Manifest for the October 27, 1881 issue, with Ranges for table of contents.
+
+```json
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "https://example.org/iiif/periodical/multi-part-collection/issue1.json",
+ "type": "Manifest",
+ "label": { "en": [ "The Tombstone Epitaph, October 27, 1881" ] },
+ "behavior": [ "paged" ],
+ "navDate": "1881-10-27T00:00:00+00:00",
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c1",
+ "type": "Canvas",
+ "label": { "en": [ "Page 1" ] },
+ "height": 4613,
+ "width": 3204,
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/page/p1",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/annotation/a1",
+ "type": "Annotation",
+ "motivation": [ "painting" ],
+ "body": {
+ "id": "https://example.org/image/page1.jpg",
+ "type": "Image",
+ "format": "image/jpeg",
+ "height": 4613,
+ "width": 3204,
+ },
+ "target": "https://example.org/iiif/periodical/multi-part-collection/canvas/c1"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c2",
+ "type": "Canvas",
+ "label": { "en": [ "Page 2" ] },
+ "height": 4613,
+ "width": 3204,
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/page/p2",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/annotation/a2",
+ "type": "Annotation",
+ "motivation": [ "painting" ],
+ "body": {
+ "id": "https://example.org/image/page2.jpg",
+ "type": "Image",
+ "format": "image/jpeg",
+ "height": 4613,
+ "width": 3204,
+ },
+ "target": "https://example.org/iiif/periodical/multi-part-collection/canvas/c2"
+ }
+ ]
+ }
+ ]
+ },
+ // Additional Canvases
+ ],
+ "structures": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/range/r0",
+ "type": "Range",
+ "label": { "en": [ "October 27, 1881" ] },
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/range/r1",
+ "type": "Range",
+ "label": { "en": [ "Yesterday's Tragedy: Three Men Hurled Into Eternity In the Duration of a Moment" ] },
+ "supplementary": { "id": "https://example.org/iiif/full-text-anno-collection", "type": "AnnotationCollection" },
+ "items": [
+ {
+ "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c1",
+ "type": "Canvas"
+ },
+ // Additional contents
+ ]
+ }
+ ]
+ }
+ ]
+}
+```
+
+>
+**Key Points**
+*
+{: .note}
+
+__Definitions__
+Classes: [Collection](#model/Collection), [Range](#model/Range), [AnnotationCollection](#model/AnnotationCollection)
+Properties: [behavior](#model/behavior), [navPlace](#model/navPlace), [navDate](#model/navDate), [structure](#model/structures), [supplementary](#model/supplementary)
+{: .note}
+
+thumbnail-nav
+sequence
+
+
+
# Audio and Video
-## Use Case 3: A 45 single with 2 tracks
+## Use Case 4: A 45 single with 2 tracks
This example is a Manifest with two Timelines, each of which represent a temporal extent during which a song is played. As in most cases, the Timeline `duration` is the same length as that of Content Resource painted into it. This example is a recording digitized from a 45 RPM 7 inch single. It demonstrates the use of `format` for the audio files' content type, `language` (One song is in English and one is in German), `behavior` with value "auto-advance" that tells a client to automatically advance to the second Timeline after playing the first, `annotations` that link to Annotation Pages of annotations with the motivation `supplementing` that provide the lyrics (one example is given afterwards) - and an `accompanyingContainer` that carries a picture of the single's cover that is shown while the songs are playing.
@@ -765,7 +946,7 @@ Properties: [duration](#model/duration), [format](#model/format), [language](#mo
{: .note}
-## Use Case 4: Movie with subtitles
+## Use Case 5: Movie with subtitles
This example is a Manifest with one Canvas that represents the temporal extent of the movie (the Canvas `duration`) and its aspect ratio (given by the `width` and `height` of the Canvas). The example demonstrates the use of a `Choice` annotation body to give two alternative versions of the movie, indicated by their `label` and `fileSize` properties as well as `height` and `width`. Subtitles are provided by an annotation that links to a VTT file. The motivation of this annotation is `supplementing` and the `provides` property of this annotation indicates what accessibility feature it provides, in this case the term `subtitles`. The `timeMode` property in this case is redundant as `trim` is the default value. The Canvas has a `placeholderContainer` that provides a poster image to show in place of the video file before the user initiates playback.
@@ -882,8 +1063,8 @@ This example is a Manifest with one Canvas that represents the temporal extent o
>
**Key Points**
-* The decision about which item in the `Choice` to play by default is client dependent. In the absence of any other decision process the client should play the first item. In this specific example, the user might make the decision after reading the `label`, or the client might make the decision based on the `fileSize` property and an assessment of the user's available bandwidth. However, the client may have no way of determining why the publisher has offered the choices, and should not prevent the user from making the choice. The cookbook demonstrates several uses of `Choice` for common use cases.
-* Slop
+* The decision about which item in the `Choice` to play by default is client dependent. In the absence of any other decision process the client should play the first item. In this specific example, the user might make the decision after reading the `label`, or the client might make the decision based on the `fileSize` property and an assessment of the user's available bandwidth. However, the client may have no way of determining why the publisher has offered the choices, and should not prevent the user from making the choice. The cookbook demonstrates several uses of `Choice` for common image and AV use cases.
+* Slop - impl note - don't interpret **very** minor discrepancies between `duration` on the different Choices and the Container `duration` as an instruction to stretch or compress the audio/video stream to match the Container duration. No real way to quantify this, just _be sensible_.
{: .note}
@@ -902,6 +1083,37 @@ Scenes have infinite height (y axis), width (x axis) and depth (z axis), where 0
The positive y axis points upwards, the positive x axis points to the right, and the positive z axis points forwards (a [right-handed cartesian coordinate system](https://en.wikipedia.org/wiki/Right-hand_rule)).
+(image of coordinate system here)
+
+## 3D Supporting Resources
+
+
+Constructs from the domain of 3D graphics are expressed in IIIF as Resources. They are associated with Scenes via Painting Annotations in the same manner as Content Resources. They aid in or enhance the rendering of Content Resources, especially in Scenes.
+
+### Cameras
+
+A Camera provides a view of a region of the Scene's space from a particular position within the Scene; the client constructs a viewport into the Scene and uses the view of one or more Cameras to render that region. The size and aspect ratio of the viewport is client and device dependent.
+
+There are two types of Camera, `PerspectiveCamera` and `OrthographicCamera`. The first Camera defined and not hidden in a Scene is the default Camera used to display Scene contents. If the Scene does not have any Cameras defined within it, then the client provides a default Camera. The type, properties and position of this default camera are client-dependent.
+
+
+### Lights
+
+There are four types of Light: AmbientLight, DirectionalLight, PointLight and SpotLight. They have a `color` and an `intensity`. SpotLight has an additional property of `angle` that determines the spread of its light cone.
+
+If the Scene has no Lights, then the client provides its own lighting as it sees fit.
+
+
+### Audio Emitters
+
+There are three types of Audio emitter: AmbientAudio, PointAudio and SpotAudio. They have a `source` (an audio Content Resource) and a `volume`.
+
+### Transforms
+
+When painting resources into Scenes, it is often necessary to resize, rotate or move them relative to the coordinate space of the Scene. These operations are specified using three Transforms: ScaleTransform, RotateTransform and TranslateTransform. Each Transform has three properties, `x`, `y` and `z` which determine how the Transform affects that axis in the local coordinate space.
+
+Transforms are added to a SpecificResource using the `transform` property, and there may be more than one applied when adding a model to a Scene. Different orders of the same set of transforms can have different results, so attention must be paid when creating the array and when processing it.
+
## Use Case 5: Simple 3D Model
@@ -954,7 +1166,11 @@ This example is a Manifest with a single Scene, with a single model of a space s
## Use Case 5a: Simple 3D Model in Configured Scene
-This example adds a Light and a Camera to the previous example, and places the model at a specific point rather than at the default origin position. The Light is green and has a position, but has its default orientation of looking along the negative-y axis as no rotation has been specified. The Camera has a position and is pointing at the model's origin via the `lookAt` property. The Camera has a `fieldOfView` of 50. The `near` and `far` properties are included to ensure the model falls within the camera's range (although unnecessary in a simple Scene like this). The Scene has a background color.
+This example adds a Light and a Camera to the previous example, and places the model at a specific point rather than at the default origin position.
+
+Annotations may use a type of Selector called a `PointSelector` to align the Annotation to a point within the Scene that is not the Scene's origin. PointSelectors have three spatial properties, `x`, `y` and `z` which give the value on that axis. They also have a temporal property `instant` which can be used if the Scene has a duration, which gives the temporal point in seconds from the start of the duration, the use of which is defined in the [section on Scenes with Durations]().
+
+The Light is green and has a position, but has its default orientation of looking along the negative-y axis as no rotation has been specified. The Camera has a position and is pointing at the model's origin via the `lookAt` property. The Camera has a `fieldOfView` of 50. The `near` and `far` properties are included to ensure the model falls within the camera's range (although unnecessary in a simple Scene like this). The Scene has a background color.
@@ -1087,64 +1303,31 @@ Properties: [backgroundColor](#model/backgroundColor), [lookAt](#model/lookAt),
## Use Case 6: Complex Scene
+Example Annotation that comments on a 3D polygon within a Scene:
-Chessboard is a Canvas with image
-more than one model
-transforms for scale and rotation
-Scene in Scene
-Exclude
-interactionMode
+```
+Todo add example
+```
+### Chessboard is a Canvas with image (not a 3D chessboard)
+A Scene or a Canvas may be treated as a content resource, referenced or described within the `body` of an Annotation. As with models and other resources, the Annotation is associated with a Scene into which the Scene or Canvas is to be nested through an Annotation `target`. The content resource Scene will be placed within the `target` Scene by aligning the coordinate origins of the two scenes. Alternately, Scene Annotations may use `PointSelector` to place the origin of the resource Scene at a specified coordinate within the `target` Scene.
+### More than one model
+### Transforms for scale and rotation
+### Exclude
+### interactionMode
-## Merge the below into the examples or into model
-This (no units for scale) allows arbitrarily scaled models to be used, including very small or very large, without needing to deal with very small or very large values. If there is a correspondence to a physical scale, then this can be asserted using the physical dimensions pattern(fwd-ref-to-phys-dims).
-
-
-
-```
-```
-
-A Scene or a Canvas may be treated as a content resource, referenced or described within the `body` of an Annotation. As with models and other resources, the Annotation is associated with a Scene into which the Scene or Canvas is to be nested through an Annotation `target`. The content resource Scene will be placed within the `target` Scene by aligning the coordinate origins of the two scenes. Alternately, Scene Annotations may use `PointSelector` to place the origin of the resource Scene at a specified coordinate within the `target` Scene.
-
-
-As with other containers in IIIF, Annotations are used to target the Scene to place content such as 3d models into the scene. Annotations are also used to add lights and cameras. A Scene can have multiple models, lights, cameras and other resources, allowing them to be grouped together. Scenes and other IIIF containers, such as Canvases, may also be embedded within Scenes, as described below in the nesting section [fwd-ref-to-nesting].
-
-```json
-{
- "id": "https://example.org/iiif/scenes/1",
- "type": "Scene",
- "label": {"en": ["Chessboard"]},
- "backgroundColor": "#000000",
- "items": [
- "Note: Annotations Live Here"
- ]
-}
-```
-As with other resources, it may be appropriate to modify the initial scale, rotation, or translation of a content resource Scene prior to painting it within another Scene. Scenes associated with SpecificResources may be manipulated through the transforms described in Transforms(transforms_section).
-
-A simple example painting one Scene into another:
-
-```json
-{
- "id": "https://example.org/iiif/3d/anno1",
- "type": "Annotation",
- "motivation": ["painting"],
- "body": {
- "id": "https://example.org/iiif/scene1",
- "type": "Scene"
- },
- "target": "https://example.org/iiif/scene2"
-}
-```
+## Use Case 7: Another Complex Scene
+What is it
+### More on Point and Fragment Selectors
A content resource may be annotated into a Scene for a period of time by use of a PointSelector that is temporally scoped by a [FragmentSelector](https://www.w3.org/TR/annotation-model/#fragment-selector). The FragmentSelector has a `value` property, the value of which follows the [media fragment syntax](https://www.w3.org/TR/media-frags/#naming-time) of `t=`. This annotation pattern uses the `refinedBy` property [defined by the W3C Web Annotation Data Model](https://www.w3.org/TR/annotation-model/#refinement-of-selection).
@@ -1231,6 +1414,8 @@ An Annotation may target a specific point in time using a PointSelector's `insta
}
```
+### Time mode
+
The Annotation's [`timeMode` property](https://iiif.io/api/presentation/3.0/#timemode) can be used to indicate the desired behavior when the duration of the content resource that is not equal to the temporal region targeted by the annotation.
It is an error to select a temporal region of a Scene that does not have a `duration`, or to select a temporal region that is not within the Scene's temporal extent. A Canvas or Scene with a `duration` may not be annotated as a content resource into a Scene that does not itself have a `duration`.
@@ -1239,7 +1424,7 @@ It is an error to select a temporal region of a Scene that does not have a `dura
An annotation that targets a Scene using a PointSelector without any temporal refinement implicitly targets the Scene's entire duration.
-Audio and 3D
+### Audio and 3D
AmbientAudio (everywhere)
@@ -1254,59 +1439,27 @@ Ambient and Point can be painted on to Canvas
hidden on audio = inaudible
-
All resources that can be added to a Scene have an implicit (e.g. Lights, Cameras) or explicit (e.g. Models, Scenes), local coordinate space. If a resource does not have an explicit coordinate space, then it is positioned at the origin of its coordinate space. In order to add a resource with its local coordinate space into a Scene with its own coordinate space, these spaces must be aligned. This done by aligning the origins of the two coordinate spaces.
-Annotations may use a type of Selector called a `PointSelector` to align the Annotation to a point within the Scene that is not the Scene's origin. PointSelectors have three spatial properties, `x`, `y` and `z` which give the value on that axis. They also have a temporal property `instant` which can be used if the Scene has a duration, which gives the temporal point in seconds from the start of the duration, the use of which is defined in the [section on Scenes with Durations]().
+"Exclude Audio"
+
+
-Example Annotation that positions a model at a point within a Scene:
-```json
-{
- "id": "https://example.org/iiif/3d/anno1",
- "type": "Annotation",
- "motivation": ["painting"],
- "body": {
- "id": "https://example.org/iiif/assets/model1.glb",
- "type": "Model"
- },
- "target": {
- "type": "SpecificResource",
- "source": [
- {
- "id": "https://example.org/iiif/scene1",
- "type": "Scene"
- }
- ],
- "selector": [
- {
- "type": "PointSelector",
- "x": -1.0,
- "y": 0.0,
- "z": 1.0
- }
- ]
- }
-}
-```
-Annotations may alternately use a type of Selector called a `WktSelector` to align the Annotation to a region with the Scene that is not the Scene's origin. WktSelectors have a single property, `value`, which is a string conforming to a WKT Linestring, LineStringZ, Polygon, or PolygonZ list of 2D or 3D coordinate points. Whether and how a region defined by a WktSelector may be translated to a single 2D or 3D coordinate point, for targeting or other purposes, is client-dependent.
-Example Annotation that comments on a 3D polygon within a Scene:
-```
-Todo add example
-```
-## Give example of refinedBy ? e.g. WktSelector + Instant
# Nesting (more about Containers as Content Resources)
+> How does this relate to model doc? What's normative and needs to be in model.md because it defines a Scene?
+
A Canvas can be painted into a Scene as an Annotation, but the 2D nature of Canvases requires special consideration due to important differences between Canvases and Scenes. A Canvas describes a bounded 2D space with finite `height` and `width` measured in pixels with a pixel origin at the top-left corner of the Canvas, while Scenes describe a boundless 3D space with x, y, and z axes of arbitrary coordinate units and a coordinate origin at the center of the space. It is important to note that in many cases the pixel scale used by a Canvas or a 2D image content resource will not be in proportion to the desired 3D coordinate unit scale in a Scene.
When a Canvas is painted as an Annotation targeting a Scene, the top-left corner of the Canvas (the pixel origin) is aligned with the 3D coordinate origin of the Scene. The top edge of the Canvas is aligned with (e.g., is colinear to) the positive x axis extending from the coordinate origin. The left edge of the Canvas is aligned with (e.g., is colinear to) the negative y axis extending from the coordinate origin. The Canvas is scaled to the Scene such that the pixel dimensions correspond to 3D coordinate units - a Canvas 200 pixels wide and 400 pixels high will extend 200 coordinate units across the x axis and 400 coordinate units across the y axis. Please note: direction terms "top", "bottom", "right", and "left" used in this section refer to the frame of reference of the Canvas itself, not the Scene into which the Canvas is painted.
@@ -1319,9 +1472,11 @@ A Canvas in a Scene has a specific forward face and a backward face. By default,
A `PointSelector` can be used to modify the point at which the Canvas will be painted, by establishing a new point to align with the top-left corner of the Canvas instead of the Scene coordinate origin. Transforms can also be used to modify Canvas rotation, scale, or translation.
+
-When a Scene is nested into another Scene, the `backgroundColor` of the Scene to be nested should be ignored as it is non-sensible to import. All Annotations painted into the Scene to be nested will be painted into the Scene into which content is being nested, including Light or Camera resources. If the Scene to be nested has one or more Camera Annotations while the Scene into which content is being nested does not, the first Camera Annotation from the nested Scene will become the default Camera for the overall Scene.
-
----
-
-
-
-
-
-# Annotations
-
-
-
-## Comment Annotations
-
-
-
-## Choice of Alternative Resources
-
-## Use Case : Multi-spectral Images with Comments
-
-
-## Embedded Content
-
-e.g., painting TextualBody on Canvas
-
-Todo: This is mostly copy-pasted from properties, is it needed here?
-It is important to be able to position the textual body of an annotation within the Container's space that the annotation also targets. For example, a description of part of an image in a Canvas should be positioned such that it does not obscure the image region itself and labels to be displayed as part of a Scene should not be rendered such that the text is hidden by the three dimensional geometry of the model. The positioning of the textual body in a container is accomplished through the `position` property, which has as a value a Specific Resource identifying the targeted container as the source and a selector defining how the textual body should be positioned in the targeted container. If this property is not supplied, then the client should do its best to ensure the content is visible to the user.
-
-
-
+## Scene in Scene
+Scenes and other IIIF containers, such as Canvases, may also be embedded within Scenes, as described below in the nesting section [fwd-ref-to-nesting].
-## Non Rectangular Segments
-
-SvgSelector - move to SpecificResource too ^^
+```json
+{
+ "id": "https://example.org/iiif/scenes/1",
+ "type": "Scene",
+ "label": {"en": ["Chessboard"]},
+ "backgroundColor": "#000000",
+ "items": [
+ "Note: Annotations Live Here"
+ ]
+}
+```
+As with other resources, it may be appropriate to modify the initial scale, rotation, or translation of a content resource Scene prior to painting it within another Scene. Scenes associated with SpecificResources may be manipulated through the transforms described in Transforms(transforms_section).
+A simple example painting one Scene into another:
-## Style
+```json
+{
+ "id": "https://example.org/iiif/3d/anno1",
+ "type": "Annotation",
+ "motivation": ["painting"],
+ "body": {
+ "id": "https://example.org/iiif/scene1",
+ "type": "Scene"
+ },
+ "target": "https://example.org/iiif/scene2"
+}
+```
-Move to SpecificResource
+When a Scene is nested into another Scene, the `backgroundColor` of the Scene to be nested should be ignored as it is non-sensible to import. All Annotations painted into the Scene to be nested will be painted into the Scene into which content is being nested, including Light or Camera resources. If the Scene to be nested has one or more Camera Annotations while the Scene into which content is being nested does not, the first Camera Annotation from the nested Scene will become the default Camera for the overall Scene.
-## Rotation
-## Hotspot Linking and Activation
+# Annotations
-Move to SpecificResource
+In the examples so far, Annotations have been used to associate the images, audio and other Content Resources with their Containers for presentation. IIIF uses the same W3C standard for the perhaps more familiar _annotation_ concepts of commenting, tagging, describing and so on. Annotations can carry textual transcriptions or translations of the content, discussion about the content and any other linking between resources.
+Whereas annotations that associate content resources with Containers are included in the `items` property of the Container, all other types of Annotation are referenced from the `annotations` property. Containers, Manifests, Collections and Ranges can all have this property, linking to relevant annotations. As with the `items` property, annotations are grouped into one or more AnnotationPage resources. These are usually external references.
+```
+Manifest
+ items
+ Canvas
+ annotations
+ AnnotationPage
+ items
+ Annotation
+```
## Annotation Page
@@ -1389,10 +1547,9 @@ Move to SpecificResource
link to https://developer.mozilla.org/en-US/docs/Web/CSS/z-index
-
## Annotation Collection
-deal with this:
+deal with this: (use in example)
https://github.com/IIIF/api/pull/2304/files#diff-cc70f02818f6bed2b14dfbf8bf3206e0825047951c8e83ad56fc73e489f82ac4R1757
use totalItems? https://iiif.io/api/discovery/1.0/#totalitems
@@ -1400,198 +1557,57 @@ use totalItems? https://iiif.io/api/discovery/1.0/#totalitems
+## Comment Annotations
+> (examples are just the anno)
+### A comment about a segment of music
+(targets Timeline)
+"Here begins the development of the second theme"
-# Navigation
+### A comment about a face in a painting
-## Collection
+(is this a full use case?)
-IIIF Collections are ordered lists of Manifests, Collections, and/or Specific Resources. Collections allow these resources to be grouped in a hierarchical structure for navigation and other purposes.
+(targets Canvas)
+"This might be so-and-so"
-:eyes:
+(Uses Non Rectangular Segments - SvgSelector)
-## Range
+Annotations may alternately use a type of Selector called a `WktSelector` to align the Annotation to a region with the Scene that is not the Scene's origin. WktSelectors have a single property, `value`, which is a string conforming to a WKT Linestring, LineStringZ, Polygon, or PolygonZ list of 2D or 3D coordinate points. Whether and how a region defined by a WktSelector may be translated to a single 2D or 3D coordinate point, for targeting or other purposes, is client-dependent.
-IIIF Ranges are used to represent structure _WITHIN_ a Manifest beyond the default order of the Containers in the `items` property. Example uses include newspaper sections or articles, chapters within a book for a table of contents, or movements within a piece of music. Ranges can include Containers, parts of Containers via Specific Resources or fragment URIs, or other Ranges, creating a tree structure like a table of contents. The typical intent of adding a Range to the Manifest is to allow the client to display a linear or hierarchical navigation interface to enable the user to quickly move through the object's content.
-:eyes:
+### A comment about something in a Model
-## Use Case : Periodical
+(targets Scene)
+Look at this scratch in the helmet
-This example demonstrates the use of IIIF Collections to group Manifests into a hierarchy. In this case, there is a Collection for a publishing run of the _The Tombstone Epitaph_ from 1880 to 1920. This contains 41 child Collections each representing a year's worth of issues. The parent Collection and each of its child Collections use the `behavior` "multi-part" to signal that the Collections and their Manifests are part of a logical whole or contiguous set. Each of the year Collections has one Manifest for each issue of the newspaper.
+> Todo: This is mostly copy-pasted from properties, is it needed here? Use in above example.
-The top level Collection has a `navPlace` property that could be used on a "Newspapers of America" map to allow users to view newspapers by location. Each Manifest has a `navDate` property that could be used to plot the issues on a calendar-style user interface. Within each Manifest, the `structures` property provides Ranges which are used to identify individual sections of the Newspaper, and individual stories within the sections, which may be spread across multiple columns and pages. Each story's Range includes the `supplementary` property to link to an Annotation Collection that provides the text of the story.
+It is important to be able to position the textual body of an annotation within the Container's space that the annotation also targets. For example, a description of part of an image in a Canvas should be positioned such that it does not obscure the image region itself and labels to be displayed as part of a Scene should not be rendered such that the text is hidden by the three dimensional geometry of the model. The positioning of the textual body in a container is accomplished through the `position` property, which has as a value a Specific Resource identifying the targeted container as the source and a selector defining how the textual body should be positioned in the targeted container. If this property is not supplied, then the client should do its best to ensure the content is visible to the user.
-IIIF Collection with `behavior` "multi-part" that contains the individual "multi-part" Collections for each year/volume:
+> Forward ref to 3D comments with Cameras
-```json
-{
- "@context": "http://iiif.io/api/presentation/4/context.json",
- "id": "https://example.org/iiif/periodical/collection.json",
- "type": "Collection",
- "label": { "en": [ "The Tombstone Epitaph (1880-1920)" ] },
- "behavior": [ "multi-part" ],
- "navPlace": {
- "id": "https://example.org/iiif/periodical/collection/place/1",
- "type": "FeatureCollection",
- "features": [
- {
- "id": "https://example.org/iiif/periodical/collection/feature/1",
- "type": "Feature",
- "properties": {
- "label": { "en": ["Tombstone, Cochise County, Arizona"] }
- },
- "geometry": {
- "type": "Point",
- "coordinates": [31.715940, −110.064827]
- }
- }
- ]
- },
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/v1.json",
- "type": "Collection",
- "label": { "en": [ "The Tombstone Epitaph, 1880" ] }
- },
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/v2.json",
- "type": "Collection",
- "label": { "en": [ "The Tombstone Epitaph, 1881" ] }
- },
- // Additional multi-part collections for each year/volume
- ]
-}
-```
-IIIF Collection with `behavior` "multi-part" for the second volume (1881), with individual Manifests for each issue.
-```json
-{
- "@context": "http://iiif.io/api/presentation/4/context.json",
- "id": "https://example.org/iiif/periodical/multi-part-collection/v1.json",
- "type": "Collection",
- "label": { "en": [ "The Tombstone Epitaph, 1881" ] },
- "behavior": [ "multi-part" ],
- "items": [
- // Previous issues
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/issue1.json",
- "type": "Manifest",
- "label": { "en": [ "October 27, 1881" ] }
- },
- // Subsequent issues
- ]
-}
-```
+## Linking Annotations
-Manifest for the October 27, 1881 issue, with Ranges for table of contents.
-```json
-{
- "@context": "http://iiif.io/api/presentation/4/context.json",
- "id": "https://example.org/iiif/periodical/multi-part-collection/issue1.json",
- "type": "Manifest",
- "label": { "en": [ "The Tombstone Epitaph, October 27, 1881" ] },
- "behavior": [ "paged" ],
- "navDate": "1881-10-27T00:00:00+00:00",
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c1",
- "type": "Canvas",
- "label": { "en": [ "Page 1" ] },
- "height": 4613,
- "width": 3204,
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/page/p1",
- "type": "AnnotationPage",
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/annotation/a1",
- "type": "Annotation",
- "motivation": [ "painting" ],
- "body": {
- "id": "https://example.org/image/page1.jpg",
- "type": "Image",
- "format": "image/jpeg",
- "height": 4613,
- "width": 3204,
- },
- "target": "https://example.org/iiif/periodical/multi-part-collection/canvas/c1"
- }
- ]
- }
- ]
- },
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c2",
- "type": "Canvas",
- "label": { "en": [ "Page 2" ] },
- "height": 4613,
- "width": 3204,
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/page/p2",
- "type": "AnnotationPage",
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/annotation/a2",
- "type": "Annotation",
- "motivation": [ "painting" ],
- "body": {
- "id": "https://example.org/image/page2.jpg",
- "type": "Image",
- "format": "image/jpeg",
- "height": 4613,
- "width": 3204,
- },
- "target": "https://example.org/iiif/periodical/multi-part-collection/canvas/c2"
- }
- ]
- }
- ]
- },
- // Additional Canvases
- ],
- "structures": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/range/r0",
- "type": "Range",
- "label": { "en": [ "October 27, 1881" ] },
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/range/r1",
- "type": "Range",
- "label": { "en": [ "Yesterday's Tragedy: Three Men Hurled Into Eternity In the Duration of a Moment" ] },
- "supplementary": { "id": "https://example.org/iiif/full-text-anno-collection", "type": "AnnotationCollection" },
- "items": [
- {
- "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c1",
- "type": "Canvas"
- },
- // Additional contents
- ]
- }
- ]
- }
- ]
-}
-```
+Simple hotspot linking example
->
-**Key Points**
-*
-{: .note}
+----
-__Definitions__
-Classes: [Collection](#model/Collection), [Range](#model/Range), [AnnotationCollection](#model/AnnotationCollection)
-Properties: [behavior](#model/behavior), [navPlace](#model/navPlace), [navDate](#model/navDate), [structure](#model/structures), [supplementary](#model/supplementary)
-{: .note}
+## Activating Annotations
-thumbnail-nav
-sequence
+Lightweight intro here
+
+Timeline example - reach point in timeline, do something
+enables and disables?
+
+Can we use light switch example here - in 2D?
+
+Moving books? - tab moves something revealing something else
+click to fold out and fold back
@@ -1608,7 +1624,9 @@ partOf -
-# Content State and toggles
+# Content State
+
+(this + model doc should relieve Content State spec of modelling concerns and leave it entirely about protocol)
A Content State is simply any valid IIIF Presentation Resource, or part of a Presentation resource. The following are all Content States that describe a "fragment" of IIIF:
@@ -1731,8 +1749,12 @@ The mechanisms for passing Content State into a client, and exporting a Content
## Load a particular view of some resource and modify it
+⚠ what are we doing with this? Do we still allow it? It's a good use case...
+
In the previous usage, the fragment of IIIF carried by the annotation with the motivation `contentState` provides enough information for a Client to load a resource and show it. This fragment can also carry additional IIIF Presentation API resources not shown in the referred-to resource. For example, in the following example the Content State carries additional annotations not present in the original published Manifest. A client initializing from this Content State would show these additional annotations to the user:
+What to do about activating annos in the introduced content?
+
```json
{
"id": "https://example.org/import/3",
@@ -1752,309 +1774,29 @@ In the previous usage, the fragment of IIIF carried by the annotation with the m
}
]
}
-}
-```
-
-As well as adding resources not present in the referred-to resource, the Content State can also remove parts of the referred-to resource from the user's view by applying the behavior `hidden` to them:
-
-```jsonc
-{
- // What does this actually look like? I want to load bnf_chateauroux example but HIDE the illumination
- // ...
- "id": "https://iiif.io/api/cookbook/recipe/0036-composition-from-multiple-images/annotation/p0001-image",
- "type": "Annotation",
- "motivation": "painting",
- "behavior": ["hidden"]
-}
-```
-
-TODO: what is the processing algorithm for applying incoming `hidden` ?
-
-When a Content State annotation carries a Scene, a view might be initialized from a Content State that introduces an additional Camera that shows the user the point of interest.
-
-
-## Modify the Container in a particular context
-
-The techniques in the previous example are also used within a published IIIF Manifest to modify the contents of a Container in the contexts of different annotations on that Container. This technique allows IIIF to be used for _storytelling_ and other narrative applications beyond simply conveying a static Digital Object into a viewer and leaving subsequent interactions entirely in the control of the user. The `scope` property indicates to the client that the Content State provides valuable context for displaying some aspect of a Scene or other Container. In the case of a commenting annotation, this means that the Content State should be loaded when the commenting annotation is selected or otherwise highlighted.
-
-
-Consider a Scene with two models, and two `commenting` annotations:
-
-```jsonc
-{
- "id": "https://example.org/iiif/3d/whale_comment_scope_content_state.json",
- "type": "Manifest",
- "label": { "en": ["Whale Cranium and Mandible with Dynamic Commenting Annotations and Custom Per-Anno Views"] },
- "items": [
- {
- "id": "https://example.org/iiif/scene1/page/p1/1",
- "type": "Scene",
- "label": { "en": ["A Scene Containing a Whale Cranium and Mandible"] },
- "items": [
- {
- "id": "https://example.org/iiif/scene1/page/p1/1",
- "type": "AnnotationPage",
- "items": [
- {
- "id": "https://example.org/iiif/3d/anno1",
- "type": "Annotation",
- "motivation": ["painting"],
- "body": {
- "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_mandible.glb",
- "type": "Model"
- },
- "target": {
- // SpecificResource with PointSelector
- }
- },
- {
- "id": "https://example.org/iiif/3d/anno2",
- "type": "Annotation",
- "motivation": ["painting"],
- "body": {
- "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_cranium.glb",
- "type": "Model"
- },
- "target": {
- // SpecificResource with PointSelector
- }
- }
- ]
- }
- ]
- }
- ],
- "annotations": [
- {
- "id": "https://example.org/iiif/scene1/page/p1/annotations/1",
- "type": "AnnotationPage",
- "items": [
- {
- "id": "https://example.org/iiif/3d/anno7",
- "type": "Annotation",
- "motivation": ["commenting"],
- "bodyValue": "Mandibular tooth",
- "target": {
- // SpecificResource with PointSelector
- }
- },
- {
- "id": "https://example.org/iiif/3d/anno5",
- "type": "Annotation",
- "motivation": ["commenting"],
- "bodyValue": "Right pterygoid hamulus",
- "target": {
- // SpecificResource with PointSelector
- }
- }
- ]
- }
- ]
-}
-```
-
-In that form, the user is left to interpret the commenting annotations and explore the Scene. The client will render a UI that presents the two commenting annotation in some form and allow the user to navigate between them. The commenting annotations are ordered; while the user might explore them freely in the Scene they might also go "forward" from the first to the second commenting annotation and "back" to the first from the second.
-
-In many complex 3D Scenes, it may not be clear what or how to look at a particular point of interest even when the commenting annotation targets a particular point. The view may be occluded by parts of the model, or other models in the Scene. It may be useful to light the Scene differently in different contexts.
-
-In the same way an incoming Content State can modify a Scene as it initializes the client, so can a Content State attached to each (non-`painting`) annotation target modify the Scene as the user moves between different annotations.
-
-The `scope` property of an annotation `target` provides _contextual_ Content State - the viewer should modify the Scene by applying the Content State carried by the `scope` property _only when the user is in the context of that annotation_.
-
-Taking the first commenting annotation from the above example and adding a `scope` property, whose value is an annotation with the motivation `contentState`, we can introduce a new Camera specifically for this particular annotation, so that when the user selects this comment, the client will switch the view to this camera. This example also changes the background color of the Scene:
-
-```jsonc
-{
- "id": "https://example.org/iiif/3d/anno7",
- "type": "Annotation",
- "motivation": ["commenting"],
- "bodyValue": "Mandibular tooth",
- "target": {
-
- // SpecificResource with PointSelector
- // "type": "SpecificResource",
- // "source": ... the Scene...
- // "selector": ... a point ...
-
- "scope": { // a modification to the Scene, only in the context of this annotation
-
- "id": "https://example.org/iiif/3d/anno4",
- "type": "Annotation",
- "motivation": ["contentState"],
- "target": {
- "id": "https://example.org/iiif/scene1/page/p1/1",
- "type": "Scene",
- "backgroundColor": "yellow",
- "items": [
- {
- "id": "https://example.org/iiif/3d/anno8",
- "type": "Annotation",
- "motivation": ["painting"],
- "body": {
- "type": "SpecificResource",
- "source": [
- {
- "id": "https://example.org/iiif/3d/cameras/1",
- "type": "PerspectiveCamera",
- "label": {"en": ["Perspective Camera Pointed At Front of Cranium and Mandible"]},
- "fieldOfView": 50.0,
- "near": 0.10,
- "far": 2000.0
- }
- ]
- },
- "target": {
- "type": "SpecificResource",
- "source": [
- {
- "id": "https://example.org/iiif/scene1",
- "type": "Scene"
- }
- ],
- "selector": [
- {
- "type": "PointSelector",
- "x": 0.0, "y": 0.15, "z": 0.75
- }
- ]
- }
- }
- ]
- }
- }
- }
-}
-```
-
-In a storytelling or exhibition scenario, the non-painting `annotations` might be carrying informative text, or even rich HTML bodies. They can be considered to be _steps_ in the story. The use of `scope` allows a precise storytelling experience to be specified, including:
-
- - providing a specific viewpoint for each step of the narrative (or even a choice of viewpoints)
- - modifying the lighting of the Scene for each step, for example shining a spotlight on a point of interest
- - hiding parts of the Scene for a step
- - introducing additional models at a particular step
- - (and many more!)
-
-Use of `scope` is permitted in annotations on any Container type, not just Scenes. For example, a 2D narrative around a Canvas might show or hide different `painting` annotations at each step.
-
-
-
-
-
-
-## The `sequence` behavior
-
-// Is this right? Language...
-
-While all AnnotationPage `items` are inherently ordered, an Annotation Page with the behavior `sequence` is explicitly a narrative, and clients should prevent (dissuade) users from jumping about. The presence of `sequence` affects the way a client should interpret the `reset` property described below.
-
-## Content States on Manifests
-
-When an annotation with the motivation `contentState` is provided via the `annotations` property of a Manifest, rather than contextually via `scope`, it is assumed to be generally available for selection by the user at any time. A client may present such as annotations as a menu of views, allowing arbitrary jumping into any Scene (or Canvas or Timeline) from any other point.
-
-// Is there some overlap here with Range?
-
-## Processing Content States in Scopes: reset
-
-When a Content State is applied to a Container such as a Scene, it is assumed to be a "diff" - for example if 3 cameras and 4 lights are already present in the Scene, and a Content State asserts a single new Camera, the default behavior is to add this fourth Camera to the Scene and leave the existing resources as they are.
-
-The client should reset the Container to its original state before applying the diff operation. However, for narratives that cumulatively build a Scene this may lead to excessively verbose Manifests. When moving through the items of an Annotation page with the behavior `linear-nav`, the Container is not reset and the diff is cumulative; modifications from one `scope` persist into the next. This can be overridden for an individual annotation with the behavior `reset`:
-
-`linear-nav` does not inherit, but `reset` does. `reset` is the default behavior for AnnotationPage and Annotation.
-
-```json
-{
- // a story, but we reset the Scene for each content state
- "type": "AnnotationPage",
- "behavior": ["linear-nav"],
- "items": [
-
- ]
-}
-```
-
-```json
-{
- // a story, but the application of content-state is cumulative
- // what if you go backwards?
- // What if other content states have been applied before you start the story?
- // **** Is linear-nav implicitly reset on the first anno?
- // Should all anno pages reset the Scene - no because I might send you a view with a content state
- "type": "AnnotationPage",
- "behavior": ["linear-nav", "no-reset"], // no-reset is a behavior for the annos not the page
- "items": [
-
- ]
-}
-```
-
-```jsonc
-[
- {
- "id": "https://.../step-1",
- "type": "Annotation",
- "motivation": ["contentState"]
- // if you really want to ensure that any ad-hoc applied content states are wiped out,
- // then put an explicit reset here. But usually, we can start the nav by applying
- // the content state in the scope to the Scene without worrying that someone has
- // modified the Scene already.
- },
- // ....
-
-
- {
- "id": "https://.../step-20",
- "type": "Annotation",
- "motivation": ["contentState"]
- // inherit no-reset
- },
-
-
- {
- // However, this particular step (step 37) needs to reset the Scene to the initial state.
- "id": "https://.../step-37",
- "type": "Annotation",
- "motivation": ["contentState"],
- "behavior": ["reset"]
- }
-]
-```
-
-behavior: `linear-nav` -- cannot jump around only one step forward/back
-
-client _MUST_ support forward nav and _MAY_ support backward nav
-
-If you go backwards from step n in a linear-nav, **and** you have applied one or more content states during the linear-nav, the client _MAY_ reset the whole Scene to default condition and then replay the linear-nav up to step n-1. (client doesn't have to maintain infinite undo history)
-
-
-
-Before applying the content state to the Scene, the client should reset the Scene to its original state as provided by the Manifest.
-
-// I am assuming reset is always true except in `linear-nav` - otherwise it's completely unpredictable!! or is it... arbitrary navigation, state provided by initialization content states, etc...
-
-## Contribute additional information permanently
+}
+```
-Rerum inbox scenario - should be covered in CS2 protocol
-## activating - animation and interactions
+# Interactivity and Storytelling
-Annotations with the motivation `activating` are referred to as _activating_ annotations.
+Sometimes it is necessary to modify the contents of a Container in the contexts of different annotations on that Container. This technique allows IIIF to be used for _storytelling_ and other narrative applications beyond simply conveying a static Digital Object into a viewer and leaving subsequent interactions entirely in the control of the user.
-There are two uses of `activating` annotations:
+A narrative might comprise a set (an AnnotationPage) of `commenting` annotations that target different parts of the Container, for example a guided tour of a painting or a map. For a Canvas or Timeline it is usually sufficient to leave the interactivity to the client; the fact that comments target different extents implies the client must offer some affordance for those comments (typically the user can click each one), and in response the client will move the current play point of the Timeline to the commenting annotation target, or pan and zoom the viewport to show the relevant part of an image. For 3D this may not be enough; a particular comment may only make sense from a certain viewpoint (i.e., Camera), or different steps of the story require different Lights to be active.
-### Triggering a content state
-An activating annotation links a Painting Annotation to a content state. When a user interacts with the Painting Annotation - whether through clicking it, tapping it, or other client-specific behaviors - the linked content state should be processed to modify the Scene or other Container, as in the previous examples. The Painting Annotation is the target of the activating annotation, and the content state is the body value. Only one content state may be specified in the body array, but the body array may include a `TextualBody` to provide a label for the interaction. The pattern is the same as for the `linking` motivation, but rather than the client opening a new browser window on the resource specified in the `body`, it applies the modification provided by the Content State.
+## 3D Comments with Cameras
-The activating annotation is provided in a Container's `annotations` property. In this (contrived for brevity) example, if the user clicks the mandible model, the Scene background changes color:
+Consider a Scene with two models, two `commenting` annotations, and a camera. We really only want the camera to be used when the user is looking at the Mandibular tooth, by default and at other times we don't need a specific camera, we can let them explore freely.
```jsonc
{
- "id": "https://example.org/iiif/3d/activating.json",
+ "id": "https://example.org/iiif/3d/whale_comment_scope_content_state.json",
"type": "Manifest",
"label": { "en": ["Whale Cranium and Mandible with Dynamic Commenting Annotations and Custom Per-Anno Views"] },
"items": [
{
- "id": "https://example.org/iiif/scene1/scene-with-activation",
+ "id": "https://example.org/iiif/scene1/page/p1/1",
"type": "Scene",
"label": { "en": ["A Scene Containing a Whale Cranium and Mandible"] },
"items": [
@@ -2063,7 +1805,7 @@ The activating annotation is provided in a Container's `annotations` property. I
"type": "AnnotationPage",
"items": [
{
- "id": "https://example.org/iiif/3d/painting-anno-for-mandible",
+ "id": "https://example.org/iiif/3d/anno1",
"type": "Annotation",
"motivation": ["painting"],
"body": {
@@ -2073,97 +1815,281 @@ The activating annotation is provided in a Container's `annotations` property. I
"target": {
// SpecificResource with PointSelector
}
- }
- ],
- "annotations": [
+ },
{
- "id": "https://example.org/iiif/scene1/page/activators",
- "type": "AnnotationPage",
- "items": [
- {
- "id": "https://example.org/iiif/3d/anno2",
- "type": "Annotation",
- "motivation": ["activating"],
- "body": [
- {
- "type": "TextualBody",
- "value": "A label for the activation may be provided as a TextualBody"
- },
- {
- // A body where the type is a IIIF Resource (eg Scene) is the Content State to apply
- "id": "https://example.org/iiif/scene1/scene-with-activation",
- "type": "Scene",
- "backgroundColor": "#FF99AA"
- }
- ],
- "target": {
- "id": "https://example.org/iiif/3d/painting-anno-for-mandible",
- "type": "Annotation"
+ "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera",
+ "type": "Annotation",
+ "motivation": ["painting"],
+ "behavior": ["hidden"],
+ "body": {
+ "type": "SpecificResource",
+ "source": [
+ {
+ "id": "https://example.org/iiif/3d/cameras/1",
+ "type": "PerspectiveCamera",
+ "label": {"en": ["Perspective Camera Pointed At Front of Cranium and Mandible"]},
+ "fieldOfView": 50.0,
+ "near": 0.10,
+ "far": 2000.0
}
- }
- ]
+ ]
+ },
+ "target": {
+ "type": "SpecificResource",
+ "source": [
+ {
+ "id": "https://example.org/iiif/scene1",
+ "type": "Scene"
+ }
+ ],
+ "selector": [
+ {
+ "type": "PointSelector",
+ "x": 0.0, "y": 0.15, "z": 0.75
+ }
+ ]
+ }
+ },
+ {
+ "id": "https://example.org/iiif/3d/anno2",
+ "type": "Annotation",
+ "motivation": ["painting"],
+ "body": {
+ "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_cranium.glb",
+ "type": "Model"
+ },
+ "target": {
+ // SpecificResource with PointSelector
+ }
}
]
}
]
}
+ ],
+ "annotations": [
+ {
+ "id": "https://example.org/iiif/scene1/page/p1/annotations/1",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth",
+ "type": "Annotation",
+ "motivation": ["commenting"],
+ "bodyValue": "Mandibular tooth",
+ "target": {
+ // SpecificResource with PointSelector
+ }
+ },
+ {
+ "id": "https://example.org/iiif/3d/commenting-anno-for-right-pterygoid-hamulus",
+ "type": "Annotation",
+ "motivation": ["commenting"],
+ "bodyValue": "Right pterygoid hamulus",
+ "target": {
+ // SpecificResource with PointSelector
+ }
+ }
+ ]
+ }
]
}
```
+In that form, the user is left to interpret the commenting annotations and explore the Scene. The client will render a UI that presents the two commenting annotation in some form and allow the user to navigate between them. The commenting annotations are ordered; while the user might explore them freely in the Scene they might also go "forward" from the first to the second commenting annotation and "back" to the first from the second.
+
+In many complex 3D Scenes, it may not be clear what or how to look at a particular point of interest even when the commenting annotation targets a particular point. The view may be occluded by parts of the model, or other models in the Scene. In this case we only want that camera to be used for looking at the Mandibular tooth. For now, it has been given the behavior `hidden`.
+## Activating Annotations
-```json
+Annotations with the motivation `activating` are referred to as _activating_ annotations, and are used to link a resource that triggers an action with the resource(s) to change, enable or disable. In the above case the `target` of the activating annotation could be one of the commenting annotations, for which a user might click a corresponding UI element. In other scenarios the `target` could be the painting annotation of a 3D model, or an annotation that targets part of a model, or a region of a Canvas, or a point or segment of a Timeline, or any other annotation that a user could interact with (in whatever manner) to trigger an event. The `body` of the annotation is the resource that is then activated - for example, a Camera which then becomes the active viewport.
+
+`target` variations
+
+- user "walks into a room"
+- AV scrub bar reaches time t1
+- user interacts with a model
+- user touches a face in a painting
+
+We can add an additional `activating` annotation to the existing annotations, to connect them to the resources activated.
+
+Activating annotations are provided in a Container's `annotations` property. They can be mixed in with the commenting (or other interactive annotations) they target, or they can be in a separate AnnotationPage. The client should evaluate all the activating annotations it can find.
+
+> recommend they are inline in the manifest?
+
+> use cases for loading in new pages of annos later - activate the French translations
+
+
+```jsonc
{
- "items": [
+ "id": "https://example.org/iiif/3d/anno9",
+ "type": "Annotation",
+ "motivation": ["activating"],
+ "target": [
{
- "id": "https://example.org/iiif/3d/anno2",
- "type": "Annotation",
- "motivation": ["activating"],
- "body": [
- {
- "type": "TextualBody",
- "value": "A label for the activation may be provided as a TextualBody"
- }
- ],
- "target": {
- "source": {
- "id": "https://example.org/iiif/3d/painting-anno-for-mandible",
- "type": "Annotation"
- },
- "scope": {
- "type": "Annotation",
- "motivation": ["contentState"],
- "target": {
- // A body where the type is a IIIF Resource (eg Scene) is the Content State to apply
- "id": "https://example.org/iiif/scene1/scene-with-activation",
- "type": "Scene",
- "backgroundColor": "#FF99AA"
- }
- }
- }
+ "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth",
+ "type": "Annotation"
+ }
+ ],
+ "body": [
+ {
+ "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera",
+ "type": "Annotation"
}
]
}
```
-// Can you put activating annotations in `manifest.annotations`? They would work there too, you have all the information.
+The pattern is similar to that for linking (ref)
+
+In a storytelling or exhibition scenario, the non-painting `annotations` might be carrying informative text, or even rich HTML bodies. They can be considered to be _steps_ in the story. The use of activating annotations allows a precise storytelling experience to be specified, including:
+
+ - providing a specific viewpoint for each step of the narrative (or even a choice of viewpoints)
+ - modifying the lighting of the Scene for each step, for example shining a spotlight on a point of interest
+ - hiding models in the Scene at a particular step
+ - showing additional models at a particular step
+As in the above example, all the other annotations referred to by the activating annotations `target` and `body` properties are already present in the Scene from the beginning. Initially, many of them may have the behavior `hidden`, invisible until activated.
-### Triggering a named animation in a model
+The `body` is anything that is can be activated:
-> toggles: anno supplies the label. This anno's `toggles` property lists id of an activating anno that activates the animation.
+- Camera: if "hidden" the behavior is removed, and (crucially) this Camera becomes the viewport.
+- AnimationSelector: A named animation within a model is played.
+- (anything else yet?)
-Sometimes a model file has inbuilt animations. While a description of these is outside the scope of IIIF, because it is 3D-implementation-specific, as long as there is a way to refer to a model's animation(s) by name, we can connect the animation to IIIF resources.
-This pattern is similar to the above, except that:
+## Showing and hiding resources
+
+An activating annotation has two additional optional properties:
+
+* `enables`: For each annotation in the value, remove the 'hidden' behavior if it has it.
+* `disables`: For each annotation in the value, add the 'hidden' behavior if it does not have it.
+
+Hidden resources cannot be active or activated. If the values are the `id` properties of painting resources that paint models, they are hidden or made visible. If Lights, they are turned on.
+
+### Example: a light switch
+
+* Initially, a model of a light switch is painted into the Scene. A PointLight is also painted, but with the `behavior` "hidden", which means it is inactive (i.e., off). A commenting annotation with the text "Click the switch to turn the light on or off" targets the light switch. An activating annotation targets the commenting annotation, so that user interaction with the commenting annotation will trigger the activating annotation. This activating annotation has no `body`, but it does have `enables` with values that are the `id` properties of the painting annotation for the light switch model, and the activating annotation that turns the light off. It also has a `disables` with the value of its own `id` - i.e., it disables _itself_. A further activating annotation has the opposite effect. Initially this has the `behavior` "hidden" - which means it is inactive. It also targets the commenting annotation, but has no effect while hidden.
+* When the user interacts with the light switch model, the client processes any activating annotations that target it and are not hidden. In this case, the first activating annotation is triggered because while both target the switch, only the first is not hidden. This activation `enables` the light (i.e., removing its "hidden" `behavior` and therefore turning it on) and the other activating annotation, and `disables` itself.
+* If the user clicks the light again, the client again processes any activating annotations that target it and are not hidden. This time the second annotation is the active one - and it `disables` the light (turning it off) and itself, and enables the first activating annotation again.
+* Subsequent clicks simply alternate between these two states, indefinitely.
+
+
+```jsonc
+{
+ "@context": "http://iiif.io/api/presentation/4/context.json",
+ "id": "https://example.org/iiif/manifest/switch",
+ "type": "Manifest",
+ "label": { "en": [ "Light switch" ] },
+ "items": [
+ {
+ "id": "https://example.org/iiif/scene/switch/scene-1",
+ "type": "Scene",
+ "items": [
+ {
+ "id": "https://example.org/iiif/scene/switch/scene-1/painting-annotation-pages/1",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "https://example.org/iiif/painting-annotation/lightswitch-1",
+ "type": "Annotation",
+ "motivation": ["painting"],
+ "label": {
+ "en": ["A light switch"]
+ },
+ "body": {
+ "id": "https://example.org/iiif/model/models/lightswitch.gltf",
+ "type": "Model"
+ },
+ "target": "https://example.org/iiif/scene/switch/scene-1"
+ },
+ {
+ "id": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4",
+ "type": "Annotation",
+ "motivation": ["painting"],
+ "body": {
+ "id": "https://example.org/iiif/scene/switch/scene-1/lights/4/body",
+ "type": "PointLight"
+ },
+ "target": {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1",
+ "selector": [
+ {
+ "type": "PointSelector",
+ "x": 5, "y": 5, "z": 5
+ }
+ ]
+ },
+ "behavior": ["hidden"]
+ }
+ ]
+ }
+ ],
+ "annotations": [
+ {
+ "id": "https://example.org/iiif/scene/switch/scene-1/annos/1",
+ "type": "AnnotationPage",
+ "items": [
+ {
+ "id": "https://example.org/iiif/scene/switch/scene-1/annos/1/switch-comment-0",
+ "type": "Annotation",
+ "motivation": [
+ "commenting"
+ ],
+ "body": {
+ "type": "TextualBody",
+ "value": "Click the switch to turn the light on or off"
+ },
+ "target": "https://example.org/iiif/painting-annotation/lightswitch-1"
+ },
+ {
+ "id": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2",
+ "type": "Annotation",
+ "motivation": [
+ "activating"
+ ],
+ "target": "https://example.org/iiif/painting-annotation/lightswitch-1",
+ "disables": [
+ "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2"
+ ],
+ "enables": [
+ "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3",
+ "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4"
+ ]
+ },
+ {
+ "id": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3",
+ "type": "Annotation",
+ "motivation": [
+ "activating"
+ ],
+ "target": "https://example.org/iiif/painting-annotation/lightswitch-1",
+ "disables": [
+ "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3",
+ "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4"
+ ],
+ "enables": [
+ "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2"
+ ],
+ "behavior": ["hidden"]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+```
+
+### Triggering a named animation in a model
- - There is no Content State in the `body`, but there _MUST_ be a TextualBody to label the interaction. (?? must?)
- - The `target` selects a _named animation_ in the model. The `target` MUST be a SpecificResource, where the `source` is the Painting Annotation that paints the model, and the `selector` is of type `AnimationSelector` with the `value` being a string that corresponds to the animation in the model.
+Sometimes a model file has inbuilt animations. While a description of these is outside the scope of IIIF, because it is 3D-implementation-specific, as long as there is a way to refer to a model's animation(s) by name, we can connect the animation to IIIF resources.
- The format of the `value` string is implementation-specific, and will depend on how different 3D formats support addressing of animations within models. The same model can be painted multiple times into the scene, and you might want to activate only one model's animation, thus we need to refer to the annotation that paints the model, not the model directly.
+This pattern is also achieved with activating annotations, except that the body of the activating annotation references a _named animation_ in the model. The `body` MUST be a SpecificResource, where the `source` is the Painting Annotation that paints the model, and the `selector` is of type `AnimationSelector` with the `value` being a string that corresponds to the animation in the model.
+The format of the `value` string is implementation-specific, and will depend on how different 3D formats support addressing of animations within models. The same model can be painted multiple times into the scene, and you might want to activate only one model's animation, thus we need to refer to the annotation that paints the model, not the model directly.
```jsonc
@@ -2200,9 +2126,9 @@ This pattern is similar to the above, except that:
"type": "AnnotationPage",
"items": [
{
- "id": "https://example.org/iiif/3d/box-opening-activating-anno",
+ "id": "https://example.org/iiif/3d/box-opening-commenting-anno",
"type": "Annotation",
- "motivation": ["activating"],
+ "motivation": ["commenting"],
"body": [
{
"type": "TextualBody",
@@ -2210,13 +2136,30 @@ This pattern is similar to the above, except that:
}
],
"target": [
+ {
+ "id": "https://example.org/iiif/3d/painting-anno-for-music-box",
+ "type": "Annotation"
+ }
+ ]
+ }
+ {
+ "id": "https://example.org/iiif/3d/box-opening-activating-anno",
+ "type": "Annotation",
+ "motivation": ["activating"],
+ "target": [
+ {
+ "id": "https://example.org/iiif/3d/box-opening-commenting-anno",
+ "type": "Annotation"
+ }
+ ],
+ "body": [
{
"type": "SpecificResource",
"source": "https://example.org/iiif/3d/painting-anno-for-music-box",
"selector": [
{
- "type": "AnimationSelector",
- "value": "open-the-lid"
+ "type": "AnimationSelector",
+ "value": "open-the-lid"
}
]
}
@@ -2232,38 +2175,60 @@ This pattern is similar to the above, except that:
}
```
-> Toggles example
-```json
+### Modifying resource properties
+
+Many Scene interaction use cases can be accomplished using the `enables` and `disables` properties to toggle the `"behavior": ["hidden"]`, and/or using activating annotations with bodies that can be _activated_: the examples above show a Camera and then an Animation being activated. Models in the Scene can also be shown and hidden via these properties.
+
+> when to use enables and when to use the `body` of the activating anno - are they equivalent for, say, a hidden model: enable it, activate it - interchangeable?
+
+For some interactions it is necessary to do more than show or hide or "activate" resources, by changing just `"behavior": ["hidden"]`. Other properties can also be changed via the [JSON Patch](link) mechanism.
+
+```jsonc
{
- "id": "https://example.org/iiif/3d/activating-animation.json",
+ "type": "JSONPatch",
+ "patchTarget": "https://example.org/iiif/scene1/scene-with-color-change", // the Scene
+ "operations": [
+ {
+ "op": "replace",
+ "path": "/backgroundColor", // path to the property being changed.
+ "value": "#FF99AA"
+ }
+ ]
+}
+```
+
+> **This is a clear distinction like level0, level1 - a client can simply choose not to support arbitrary patching.**
+
+> Be clear that you still need to have all the patchable resources present from the start, you can't pull them in later.
+
+In the following simple example, the background color of the Scene is changed:
+
+
+```jsonc
+{
+ "id": "https://example.org/iiif/3d/property-change.json",
"type": "Manifest",
- "label": { "en": ["Music Box with lid that opens as an internal animation"] },
+ "label": { "en": ["Whale Mandible"] },
"items": [
{
- "id": "https://example.org/iiif/scene1/scene-with-activation-animation",
+ "id": "https://example.org/iiif/scene1/scene-with-color-change",
"type": "Scene",
- "label": { "en": ["A Scene Containing a Music Box"] },
+ "label": { "en": ["A Scene Containing a Whale Mandible"] },
"items": [
{
- "id": "https://example.org/iiif/scene-with-activation-animation/page/p1/1",
+ "id": "https://example.org/iiif/scene1/page/p1/1",
"type": "AnnotationPage",
"items": [
{
- "id": "https://example.org/iiif/3d/painting-anno-for-music-box",
+ "id": "https://example.org/iiif/3d/painting-anno-for-mandible",
"type": "Annotation",
"motivation": ["painting"],
"body": {
- "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/music-box.glb",
+ "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_mandible.glb",
"type": "Model"
},
- "target": {
- // SpecificResource with PointSelector
- },
- "toggles": [
- // Clicking the box opens the lid
- "https://example.org/iiif/3d/activating-anno-for-music-box"
- ]
+ "target": "https://example.org/iiif/scene1/scene-with-color-change"
}
],
"annotations": [
@@ -2272,77 +2237,41 @@ This pattern is similar to the above, except that:
"type": "AnnotationPage",
"items": [
{
- "id": "https://example.org/iiif/3d/activation-labelling-anno",
+ "id": "https://example.org/iiif/3d/color-change-commenting-anno",
"type": "Annotation",
- "motivation": ["commenting-maybe"],
+ "motivation": ["commenting"],
"body": [
{
"type": "TextualBody",
- "value": "Click me to open the lid of the box"
+ "value": "Change the background color"
}
],
- "toggles": [
- // clicking the 'Click me' opens the lid
- "https://example.org/iiif/3d/activating-anno-for-music-box"
- ],
- "target": [
- "https://example.org/iiif/3d/painting-anno-for-music-box"
- ]
- },
- {
- "id": "https://example.org/iiif/3d/activating-anno-for-music-box",
- "type": "Annotation",
- "motivation": ["activating"],
- "body": [
+ "target": [
{
- "type": "TextualBody",
- "value": "Click me to open the lid of the box"
+ "id": "https://example.org/iiif/3d/painting-anno-for-mandible", // or the Scene?
+ "type": "Annotation"
}
- ],
- "target": {
- "type": "SpecificResource",
- "source": "https://example.org/iiif/3d/painting-anno-for-music-box",
- "selector": [
- {
- "type": "AnimationSelector",
- "value": "open-the-lid"
- }
- ],
- "refinedBy": [
- // fragment time selector
- ]
- }
+ ]
}
- ]
- }
- ]
- }
-
-
-
-
- {
- "id": "https://example.org/iiif/scene1/page/activators",
- "type": "AnnotationPage",
- "items": [
{
- "id": "https://example.org/iiif/3d/box-opening-activating-anno",
+ "id": "https://example.org/iiif/3d/color-change-activating-anno",
"type": "Annotation",
"motivation": ["activating"],
- "body": [
+ "target": [
{
- "type": "TextualBody",
- "value": "Click the box to open the lid"
+ "id": "https://example.org/iiif/3d/color-change-commenting-anno",
+ "type": "Annotation"
}
],
- "target": [
+ "body": [
{
- "type": "SpecificResource",
- "source": "https://example.org/iiif/3d/painting-anno-for-music-box",
- "selector": [
+ "type": "JSONPatch",
+ "patchTarget": "https://example.org/iiif/scene1/scene-with-color-change",
+ "operations": [
{
- "type": "AnimationSelector",
- "value": "open-the-lid"
+ "op": "replace",
+ "path": "/backgroundColor",
+ "value": "#FF99AA"
}
]
}
@@ -2356,28 +2285,22 @@ This pattern is similar to the above, except that:
}
]
}
-
-
```
-// TODO
-
-activating to apply a content state and activating to trigger a named animation - use of body and target... what if we want to click a painting anno to trigger the animation?
-Can we ADD that to the target, alongside the SpecificResource with the AnimationSelector?
-
-if the `target` is an AnimationSelector, then the `body` can ONLY be TextualBody (or list of TextualBody)?
-
-There is a more general rule here!
-
-## reset
-
-See above...
+## The `sequence` behavior
+While all AnnotationPage `items` are inherently ordered, an Annotation Page with the `behavior` "sequence" is explicitly a narrative, and clients should prevent (dissuade) users from jumping about - the annotations, and the effects of them _activating_ other contents of the Container, are intended to be experienced in order and individually. Normally, a client might display all the comments in an AnnotationPage in a sidebar so they are all visible in the UI, but for an AnnotationPage with `behavior` "sequence" only show the currently active annotation text, and next and previous UI.
+## Chains of activation
+Chaining together activating annotations can then allow the implementation of, at least:
+* Specific camera position to look at an Annotation
+* Multi-step linear stories
+* Animations, including as part of stories without disrupting the flow, and looping animations (they activate themselves)
+* Interactive components such as light switches (enable/disable a light), jukeboxes (enable/disable Audio Emitter)
@@ -2396,6 +2319,22 @@ An extreme example of both physical dimension properties together is a Canvas sh
+# Other stuff
+
+## Embedded Content
+
+e.g., painting TextualBody on Canvas
+
+
+## Style
+
+### Rotation
+
+
+
+
+
+
# Protocol
@@ -2452,4 +2391,4 @@ The key words _MUST_, _MUST NOT_, _REQUIRED_, _SHALL_, _SHALL NOT_, _SHOULD_, _S
## Change Log
-"Exclude Audio"
+
diff --git a/source/presentation/4.0/model.md b/source/presentation/4.0/model.md
index 79858e833..a3e56086a 100644
--- a/source/presentation/4.0/model.md
+++ b/source/presentation/4.0/model.md
@@ -1155,7 +1155,7 @@ TODO: Address https://github.com/IIIF/api/issues/2318
| `sequence` | Valid only on Ranges, where the Range is [referenced][prezi30-terminology] in the `structures` property of a Manifest. Ranges that have this behavior represent different orderings of the Containers listed in the `items` property of the Manifest, and user interfaces that interact with this order _SHOULD_ use the order within the selected Range, rather than the default order of `items`. Disjoint with `thumbnail-nav` and `no-nav`.|
| `thumbnail-nav`{: style="white-space:nowrap;"} | Valid only on Ranges. Ranges that have this behavior _MAY_ be used by the client to present an alternative navigation or overview based on thumbnails, such as regular keyframes along a timeline for a video, or sections of a long scroll. Clients _SHOULD NOT_ use them to generate a conventional table of contents. Child Ranges of a Range with this behavior _MUST_ have a suitable `thumbnail` property. Disjoint with `sequence` and `no-nav`.|
| `no-nav` | Valid only on Ranges. Ranges that have this behavior _MUST NOT_ be displayed to the user in a navigation hierarchy. This allows for Ranges to be present that capture unnamed regions with no interesting content, such as the set of blank pages at the beginning of a book, or dead air between parts of a performance, that are still part of the Manifest but do not need to be navigated to directly. Disjoint with `sequence` and `thumbnail-nav`.|
-| `linear-nav` | FIXME: ... |
+| `linear-nav` | FIXME: Obsolete? use `sequence`, now valid for AnnotationPage as well as Range |
| | **Miscellaneous Behaviors** |
| `hidden` | Valid on Annotation Collections, Annotation Pages, Annotations, Specific Resources, Lights, Cameras and Choices. If this behavior is provided, then the client _SHOULD NOT_ render the resource by default, but allow the user to turn it on and off. This behavior does not inherit, as it is not valid on Collections, Manifests, Ranges or Canvases. |
| `reset` | Valid on Annotations with a scope property. FIXME: ... |