diff --git a/source/presentation/4.0/index.md b/source/presentation/4.0/index.md
index 2d7a29853..824934f97 100644
--- a/source/presentation/4.0/index.md
+++ b/source/presentation/4.0/index.md
@@ -1270,12 +1270,11 @@ The Light is green and has a position, but has its default orientation of lookin
},
"target": {
"type": "SpecificResource",
- "source": [
- {
- "id": "https://example.org/iiif/scene1/page/p1/1",
- "type": "Scene"
- }
- ],
+ "source":
+ {
+ "id": "https://example.org/iiif/scene1/page/p1/1",
+ "type": "Scene"
+ },
"selector": [
{
"type": "PointSelector",
@@ -1290,48 +1289,51 @@ The Light is green and has a position, but has its default orientation of lookin
"id": "https://example.org/iiif/3d/anno2",
"type": "Annotation",
"motivation": ["painting"],
- "body": {
- "id": "https://example.org/iiif/3d/cameras/1",
- "type": "PerspectiveCamera",
- "label": {"en": ["Perspective Camera 1"]},
- "lookAt": {
- "id": "https://example.org/iiif/3d/anno1",
- "type": "Annotation"
- },
- "near": 1,
- "far": 100,
- "fieldOfView": 50
- },
- "target": {
- "type": "SpecificResource",
- "source": [
+ "body": [
+ {
+ "id": "https://example.org/iiif/3d/cameras/1",
+ "type": "PerspectiveCamera",
+ "label": {"en": ["Perspective Camera 1"]},
+ "lookAt": {
+ "id": "https://example.org/iiif/3d/anno1",
+ "type": "Annotation"
+ },
+ "near": 1,
+ "far": 100,
+ "fieldOfView": 50
+ }
+ ],
+ "target": [
+ {
+ "type": "SpecificResource",
+ "source":
{
"id": "https://example.org/iiif/scene1/page/p1/1",
"type": "Scene"
- }
- ],
- "selector": [
- {
- "type": "PointSelector",
- "x": 0.0,
- "y": 6.0,
- "z": 10.0
- }
- ]
- }
+ },
+ "selector": [
+ {
+ "type": "PointSelector",
+ "x": 0.0,
+ "y": 6.0,
+ "z": 10.0
+ }
+ ]
+ }
+ ]
},
{
"id": "https://example.org/iiif/3d/anno2",
"type": "Annotation",
"motivation": ["painting"],
- "body": {
+ "body": [{
"id": "https://example.org/iiif/3d/lights/1",
"type": "SpotLight",
"label": {"en": ["Spot Light 1"]},
"angle": 90.0,
"color": "#A0FFA0"
- },
- "target": {
+ }],
+ "target": [{
"type": "SpecificResource",
"source": {
"id": "https://example.org/iiif/scene1/page/p1/1",
@@ -1345,7 +1347,7 @@ The Light is green and has a position, but has its default orientation of lookin
"z": 1.0
}
]
- }
+ }]
}
]
}
@@ -1392,13 +1394,13 @@ This example is a Manifest with a single Scene with multiple models painted into
"id": "https://example.org/iiif/3d/anno1",
"type": "Annotation",
"motivation": ["painting"],
- "body": {
+ "body": [{
"id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/chess/pawn.glb",
"label": {"en": ["Pawn 1"]},
"type": "Model",
"format": "model/gltf-binary"
- },
- "target": {
+ }],
+ "target": [{
"type": "SpecificResource",
"source": {
"id": "https://example.org/iiif/scene1/page/p1/1",
@@ -1412,22 +1414,21 @@ This example is a Manifest with a single Scene with multiple models painted into
"z": 0.0
}
]
- }
+ }]
},
{
"id": "https://example.org/iiif/3d/anno1",
"type": "Annotation",
"motivation": ["painting"],
- "body": {
+ "body": [{
"type": "SpecificResource",
- "source": [
+ "source":
{
"id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/chess/pawn.glb",
"label": {"en": ["Pawn 2 tipped over"]},
"type": "Model",
"format": "model/gltf-binary"
- }
- ],
+ },
"transform": [
{
"type": "RotateTransform",
@@ -1442,8 +1443,8 @@ This example is a Manifest with a single Scene with multiple models painted into
"z": 0.0
}
]
- },
- "target": {
+ }],
+ "target": [{
"type": "SpecificResource",
"source": {
"id": "https://example.org/iiif/scene1/page/p1/1",
@@ -1457,23 +1458,22 @@ This example is a Manifest with a single Scene with multiple models painted into
"z": 3.0
}
]
- }
+ }]
},
{
"id": "https://example.org/iiif/3d/anno1",
"type": "Annotation",
"motivation": ["painting"],
"exclude": ["Audio", "Lights"],
- "body": {
+ "body": [{
"type": "SpecificResource",
- "source": [
+ "source":
{
"id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/chess/queen.glb",
"label": {"en": ["Queen"]},
"type": "Model",
"format": "model/gltf-binary"
- }
- ],
+ },
"transform": [
{
"type": "ScaleTransform",
@@ -1482,8 +1482,8 @@ This example is a Manifest with a single Scene with multiple models painted into
"z": 1.5
},
]
- },
- "target": {
+ }],
+ "target": [{
"type": "SpecificResource",
"source": {
"id": "https://example.org/iiif/scene1/page/p1/1",
@@ -1498,6 +1498,7 @@ This example is a Manifest with a single Scene with multiple models painted into
}
]
}
+ ]
}
]
}
@@ -1558,7 +1559,7 @@ In this example, the audio content resources have durations that do not match th
"id": "https://example.org/iiif/3d/anno1",
"type": "Annotation",
"motivation": ["painting"],
- "body": {
+ "body": [{
"id": "https://example.org/iiif/audio/1",
"type": "AmbientAudio",
"source": {
@@ -1572,15 +1573,20 @@ In this example, the audio content resources have durations that do not match th
"unit": "relative",
"quantityValue": 0.1
}
- },
- "target": "https://example.org/iiif/scene1"
+ }],
+ "target": [
+ {
+ "id": "https://example.org/iiif/scene1",
+ "type": "Scene"
+ }
+ ]
},
{
"id": "https://example.org/iiif/3d/anno2",
"type": "Annotation",
"motivation": ["painting"],
"timeMode": "trim",
- "body": {
+ "body": [{
"id": "https://example.org/iiif/audio/2",
"type": "PointAudio",
"source": {
@@ -1594,16 +1600,15 @@ In this example, the audio content resources have durations that do not match th
"unit": "relative",
"quantityValue": 0.2
}
- },
- "target": {
+ }],
+ "target": [{
"id": "https://example.org/iiif/selectors/anno2",
"type": "SpecificResource",
- "source": [
+ "source":
{
"id": "https://example.org/iiif/scene1",
"type": "Scene"
- }
- ],
+ },
"selector": [
{
"id": "https://example.org/uuid/9fbd580b-895b-41b9-974a-1553329037f2",
@@ -1618,14 +1623,14 @@ In this example, the audio content resources have durations that do not match th
}
}
]
- }
+ }]
},
{
"id": "https://example.org/iiif/3d/anno3",
"type": "Annotation",
"motivation": ["painting"],
"timeMode": "loop",
- "body": {
+ "body": [{
"id": "https://example.org/iiif/audio/3",
"type": "SpotAudio",
"source": {
@@ -1641,8 +1646,13 @@ In this example, the audio content resources have durations that do not match th
"quantityValue": 0.3
},
"lookAt": "https://example.org/iiif/scene1"
- },
- "target": "https://example.org/iiif/scene1#xyz=3,0,-2&t=30,60"
+ }],
+ "target": [
+ {
+ "id": "https://example.org/iiif/scene1#xyz=3,0,-2&t=30,60",
+ "type": "Scene"
+ }
+ ]
}
],
"annotations": [
@@ -1650,24 +1660,29 @@ In this example, the audio content resources have durations that do not match th
"id": "https://example.org/iiif/3d/commenting",
"type": "Annotation",
"motivation": ["commenting"],
- "bodyValue": "This is the point when the percussion stops playing and the tuba begins playing.",
- "target": {
+ "body": [
+ {
+ "type": "TextualBody",
+ "value": "This is the point when the percussion stops playing and the tuba begins playing."
+ }
+ ],
+ "target": [{
"type": "SpecificResource",
- "source": [
+ "source":
{
"id": "https://example.org/iiif/scene1",
"type": "Scene"
}
- ],
+ ,
"selector": [
{
"type": "PointSelector",
"instant": 30.0
}
]
- }
- },
- ],
+ }]
+ }
+ ]
}
]
}
@@ -1865,14 +1880,14 @@ A comment on a Canvas can target a non-rectangular area. This example uses a `S
"id": "https://example.org/iiif/presentation/examples/commenting/anno/2",
"type": "Annotation",
"motivation": [ "commenting" ],
- "body": {
+ "body": [{
"id": "https://example.org/iiif/presentation/examples/commenting/anno/2/person2",
"type": "TextualBody",
"language": "en",
"format": "text/plain",
"value": "Note the expressive eyes of the subject of this painting."
- },
- "target": {
+ }],
+ "target": [{
"type": "SpecificResource",
"source": {
"id": "https://example.org/iiif/presentation/examples/commenting/canvas/2",
@@ -1885,7 +1900,7 @@ A comment on a Canvas can target a non-rectangular area. This example uses a `S
"value": " ... "
}
]
- }
+ }]
}
```
@@ -2002,53 +2017,20 @@ The resource the user should be taken to is the `body` of the annotation, and th
## 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 exhibitions, storytelling (fwd ref) and other interactive applications beyond simply conveying a set of static resources in a Container.
-
-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. The `target` of the activating annotation could be a commenting annotation, 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. Even a volume of space in a Scene or an extent of time in a Container with `duration` could be the `target`, so that when the user "enters" that region or extent, something happens.
-
-The `body` of the annotation is then activated. This has different processing requirements depending on what the body is:
-
-* If the body is a reference to a Painting Annotation:
- * if the annotation has the `behavior` "hidden", then remove "hidden" from the `behavior`.
- * if the annotation paints a Camera, make that Camera the active Camera (i.e., make this the viewport) (see [ref]).
-* If the body is a SpecificResource with a `selector` property with the type "AnimationSelector", play the animation named by the `value` property of the Selector. (see [ref]).
-* Processing for other body types can be found in the [IIIF Cookbook][ref]
+Sometimes it is necessary to modify the state of resources. Annotations with the motivation `activating` are referred to as _activating_ annotations, and are used to change resources from their initial state defined in the Manifest or from their current state. They allow IIIF to be used for interactive exhibitions, storytelling, digital dioramas and other interactive applications beyond simply conveying a set of static resources in a Container.
-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.
-
-```jsonc
-{
- "id": "https://example.org/iiif/3d/anno9",
- "type": "Annotation",
- "motivation": ["activating"],
- "target": [
- {
- "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-to-view-tooth",
- "type": "Annotation"
- }
- ]
-}
-```
+The `target` of the activating annotation is the resource that triggers an action. This could be a commenting annotation, 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. Even a volume of space in a Scene or an extent of time in a Container with `duration` could be the `target`. When that volume or time extent is triggered - which might be the user entering that volume or the playhead reaching the extent independently of user interaction - something happens.
+This specification does not define how a client indicates to a user that a resource is able to be interacted with.
-### Showing and hiding resources
+The body of the activating annotation is always an ordered list of Specific Resources, each with `source` and `action` properties. The `source` is the resource to be acted upon in some way, and the `action` property is an ordered list of named actions to perform on that resource. Valid values include "show", "hide", "enable", "disable", "start", "stop", "reset" and "select".
-An activating annotation has two additional optional properties:
+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 Annotation Page. The client should evaluate all of the enabled activating annotations it can find.
-* `enables`: For each Annotation or AnnotationPage in the value, remove the 'hidden' behavior if it has it.
-* `disables`: For each Annotation or AnnotationPage in the value, add the 'hidden' behavior if it does not have it.
-If the values are the `id` properties of painting annotations that paint models, `enables` makes them visible and `disables` hides them. If they paint Lights, `enables` turns them on and `disables` turns them off.
+### Hiding and disabling resources
-Referencing a Painting Annotation as the `body` of an activating annotation implicitly enables it, as if it had been listed in `enables`. The inverse is not always true - for example, referencing a Camera in `enables` removes the "hidden" `behavior` and therefore allows it to be included in the client's evaluation of what the default camera is, but does not perform the additional action of changing the viewport to that Camera. For Lights and Models in a Scene, the two are equivalent because no _additional_ processing behavior is provided by this specification.
-
-For many use cases, the activating annotations don't need bodies. The following example demonstrates a light switch that can be toggled on and off:
+A resource with the `behavior` value "hidden" is not rendered by the client. A resource with the `behavior` value "disabled" is not available for user interaction and does not trigger any actions. The following example is a light switch that can be toggled on and off using activating annotations that result in these behaviors being applied or removed. It demonstrates a painted resource - a light - being shown and hidden, and activating annotations being enabled and disabled. Both of these are done by the client processing the action properties of the activating annotation bodies: the actions "show" and "hide" remove or add the behavior value "hidden", and the actions "enable" and "disable" modify the behavior value "disabled".
```jsonc
{
@@ -2125,12 +2107,22 @@ For many use cases, the activating annotations don't need bodies. The following
"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"
+ "body": [
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2",
+ "action": ["disable"]
+ },
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3",
+ "action": ["enable"]
+ },
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4",
+ "action": ["show"]
+ }
]
},
{
@@ -2140,14 +2132,24 @@ For many use cases, the activating annotations don't need bodies. The following
"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"
+ "body": [
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3",
+ "action": ["disable"]
+ },
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4",
+ "action": ["hide"]
+ },
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2",
+ "action": ["enable"]
+ }
],
- "behavior": ["hidden"]
+ "behavior": ["disabled"]
}
]
}
@@ -2157,9 +2159,10 @@ For many use cases, the activating annotations don't need bodies. The following
}
```
-* 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.
+* 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 painting annotation that paints the switch, so that user interaction with the light switch will trigger the activating annotation. This activating annotation has a `body` property with three Specific Resources. The first enables the "off" activating annotation, the second shows the PointLight, and the last disables the activating annotation _itself_ - this activating annotation can no longer be activated by a user interaction with the light switch model (its `target`).
+* A further activating annotation has the opposite effect. Initially this has the `behavior` "disabled" - which means it is inactive. It also targets the painting annotation, but has no effect while disabled.
+* When the user interacts with the light switch model, the client processes any activating annotations that target it and are enabled. In this case, the first activating annotation is triggered because while both target the switch, only the first is enabled. This activation shows the light (i.e., removes its "hidden" `behavior` and therefore turning it on) and enables 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 disabled. This time the second activating annotation is the enabled one - and it hides the light (turning it off) and disables itself, and enables the first activating annotation again.
* Subsequent clicks simply alternate between these two states, indefinitely.
@@ -2167,9 +2170,9 @@ For many use cases, the activating annotations don't need bodies. The following
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 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.
+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` is a Specific Resource, 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 name of 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.
+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 painted instance of the model's animation, thus we need to refer to the annotation that paints the model, not the model directly.
```jsonc
@@ -2212,7 +2215,7 @@ The format of the `value` string is implementation-specific, and will depend on
"body": [
{
"type": "TextualBody",
- "value": "Click the box to open the lid"
+ "value": "Click me to open the lid"
}
],
"target": [
@@ -2241,7 +2244,8 @@ The format of the `value` string is implementation-specific, and will depend on
"type": "AnimationSelector",
"value": "open-the-lid"
}
- ]
+ ],
+ "action": ["start"]
}
]
}
@@ -2254,9 +2258,12 @@ The format of the `value` string is implementation-specific, and will depend on
]
}
```
+
+
### 3D Comments with Cameras
-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 the following example, the user can explore the Scene freely, but when they select a particular comment, a specific Camera that was previously hidden (unavailable to the user) is activated, moving the user (i.e., setting the viewport) to a chosen position suitable for looking at the point of interest:
+It is possible to associate a particular camera with a particular commenting annotation. In many complex 3D Scenes, it may not be clear from where to look at a particular point of interest. The view may be occluded by parts of the model, or other models in the Scene. In the following example, the user can explore the Scene freely, but when they select a particular comment, a specific Camera that was previously hidden (unavailable to the user) is activated, moving the user (i.e., setting the viewport) to a chosen position suitable for looking at the point of interest:
+
```jsonc
{
@@ -2290,34 +2297,33 @@ In many complex 3D Scenes, it may not be clear what or how to look at a particul
"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
- }
- ]
- }
+ "body": [
+ {
+ "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",
@@ -2345,7 +2351,12 @@ In many complex 3D Scenes, it may not be clear what or how to look at a particul
"id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth",
"type": "Annotation",
"motivation": ["commenting"],
- "bodyValue": "Mandibular tooth",
+ "body": [
+ {
+ "type": "TextualBody",
+ "value": "Mandibular tooth"
+ }
+ ],
"target": {
// SpecificResource with PointSelector
}
@@ -2354,12 +2365,17 @@ In many complex 3D Scenes, it may not be clear what or how to look at a particul
"id": "https://example.org/iiif/3d/commenting-anno-for-right-pterygoid-hamulus",
"type": "Annotation",
"motivation": ["commenting"],
- "bodyValue": "Right pterygoid hamulus",
+ "body": [
+ {
+ "type": "TextualBody",
+ "value": "Right pterygoid hamulus"
+ }
+ ],
"target": {
// SpecificResource with PointSelector
}
},
- {
+ {
"id": "https://example.org/iiif/3d/anno9",
"type": "Annotation",
"motivation": ["activating"],
@@ -2371,8 +2387,9 @@ In many complex 3D Scenes, it may not be clear what or how to look at a particul
],
"body": [
{
- "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth",
- "type": "Annotation"
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth",
+ "action": ["show", "enable", "select"]
}
]
}
@@ -2393,26 +2410,42 @@ Camera when annotation selected:
-# Integration
+#### Using scope to select a Camera
-seeAlso, service(s), extensions
-mention search, image api, auth
+The previous example can also be expressed in a more concise form by providing a reference to the Camera in the `scope` property of the commenting annotation.
-profile for seeAlso
+The commenting annotation now looks like this:
-partOf -
+```json
+{
+ "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth",
+ "type": "Annotation",
+ "motivation": ["commenting"],
+ "bodyValue": "Mandibular tooth",
+ "scope": [
+ {
+ "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth",
+ "type": "Annotation"
+ }
+ ],
+ "target": {
+ // SpecificResource with PointSelector
+ }
+},
+```
-Talk about Content State and use the phrase "Content State Annotations"
-(we think we now _don't_ need to write a content state 2 spec ???)
+... and the activating annotation is no longer required.
+This only works for cameras.
+Repeat full example? no, link to external.
-# Interactivity, Guided Viewing and Storytelling
+### Interactivity, Guided Viewing and Storytelling
-A narrative might comprise 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.
+Activating annotations add explicit mechanisms for interactive user experiences such as guided viewing and storytelling. A narrative might comprise an Annotation Page 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.
-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 (back ref) allows a precise storytelling experience to be specified, including:
+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
@@ -2421,25 +2454,13 @@ In a storytelling or exhibition scenario, the non-painting `annotations` might b
All the 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.
+Interactive examples are provided as recipes in the [IIIF Cookbook](link).
-## 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)
+#### The `sequence` behavior
+While all Annotation Page `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 Annotation Page in a sidebar so they are all visible in the UI, but for an Annotation Page with `behavior` "sequence" only show the currently active annotation text, and next and previous UI.
-## Storytelling example
-
-* Something really cool that brings a lot of things together!
# Conveying Physical Dimensions
@@ -2456,17 +2477,65 @@ An extreme example of both physical dimension properties together is a Canvas sh
-# Other stuff
+# Integration
+
+seeAlso, service(s), extensions
+mention search, image api, auth
+
+profile for seeAlso
+
+partOf -
+
+Talk about Content State and use the phrase "Content State Annotations" - how you transmit IIIF from software to software.
+
+## Authentication
+
+It is possible to include Image API service descriptions within the Manifest, and within those it is also possible to include links to the Authentication API's services that are needed to interact with the image content. The first time an Authentication API service is included within a Manifest, it _MUST_ be the complete description. Subsequent references _SHOULD_ be just the URI of the service, and clients are expected to look up the details from the full description by matching the URI. Clients _MUST_ anticipate situations where the Authentication service description in the Manifest is out of date: the source of truth is the Image Information document, or other system that references the Authentication API services.
-## Embedded Content
-e.g., painting TextualBody on Canvas
+# Other stuff
+
## Style
### Rotation
+An image might not be correctly aligned with the Canvas, and require rotation as it is painted. In the following example, the image is painted with a 90-degree rotation. This example uses the ImageApiSelector to convey the number of degrees of the rotation. As this particular image has an image service, the client can use the Image API to request an image that has already been rotated on the server, or it can use the information in the ImageApiSelector to rotate the image itself.
+
+```json
+{
+ "id": "http://example.org/iiif/book1/annotation/anno1",
+ "type": "Annotation",
+ "motivation": ["painting"],
+ "body": [
+ {
+ "type": "SpecificResource",
+ "source": {
+ "id": "http://example.org/iiif/book1-page1/my-image.jpg",
+ "type": "Image",
+ "service": {
+ "id": "http://example.org/iiif/book1-page1",
+ "type": "ImageService3",
+ "profile": "level2"
+ }
+ },
+ "selector": {
+ "type": "ImageApiSelector",
+ "rotation": "90"
+ }
+ }
+ ],
+ "target": [
+ {
+ "id": "http://example.org/iiif/book1/canvas/p1#xywh=50,50,320,240",
+ "type": "Canvas"
+ }
+ ]
+}
+
+```
+
@@ -2519,11 +2588,7 @@ The HTTP server _MUST_ follow the [CORS requirements][org-w3c-cors] to enable br
Responses _SHOULD_ be compressed by the server as there are significant performance gains to be made for very repetitive data structures.
-## Authentication
-
-It may be necessary to restrict access to the descriptions made available via the Presentation API. As the primary means of interaction with the descriptions is by web browsers using XmlHttpRequests across domains, there are some considerations regarding the most appropriate methods for authenticating users and authorizing their access. The approach taken is described in the [Authentication][iiif-auth] specification, and requires requesting a token to add to the requests to identify the user. This token might also be used for other requests defined by other APIs.
-It is possible to include Image API service descriptions within the Manifest, and within those it is also possible to include links to the Authentication API's services that are needed to interact with the image content. The first time an Authentication API service is included within a Manifest, it _MUST_ be the complete description. Subsequent references _SHOULD_ be just the URI of the service, and clients are expected to look up the details from the full description by matching the URI. Clients _MUST_ anticipate situations where the Authentication service description in the Manifest is out of date: the source of truth is the Image Information document, or other system that references the Authentication API services.
# Accessibility
diff --git a/source/presentation/4.0/model.md b/source/presentation/4.0/model.md
index 71572a609..06f8415d7 100644
--- a/source/presentation/4.0/model.md
+++ b/source/presentation/4.0/model.md
@@ -653,6 +653,7 @@ A IIIF Image API Selector _MAY_ have the following properties: [id](#id), [regio
}
```
+TODO The ImageApiSelector can be used on a static image, you don't need an Image Service.
### Range
{: #Range}
@@ -1129,6 +1130,38 @@ The value of `accompanyingContainer` _MUST_ be a JSON object with the `id` and `
}
```
+### action
+{: #action}
+
+Only valid on SpecificResource when bodies of activating annotations
+
+body of the activating anno is an ordered list of SpecificResource
+
+...which may have selectors eg for AnimationSelector
+...but may just have action which are processed in order; client performs the action on the source.
+
+The client must perform all the actions; if it can't perform all of them it must not perform any.
+If the activating annotation that is currently being processed is disabled as part of that processing, don't stop processing the ordered list, keep going through to the end.
+
+Only process one set of activating anno bodies at a time. If a body causes another activating anno to be triggered, queue up that activating anno and don't tackle it until you've finished processing all the bodies of the current one.
+
+values are:
+
+ * enable (make selectable, or makes an activating anno triggerable)
+ * disable (inverse)
+ * show (removes behavior:hidden)
+ * hide (applies behavior:hidden)
+ * reset (rewind AV to beginning)
+ * stop (animations in models; time-based content resources that are not painted into duration)
+ * start (ditto)
+ * select (rarely used because scope)
+
+* A Specific Resource _MAY_ have the `action` property.
+ Clients _SHOULD_ process the `action` property on Specific Resources.
+* Other types of resource _MUST NOT_ have the `action` property.
+ Clients _SHOULD_ ignore `action` on other types of resource.
+
+
### angle
{: #angle}
@@ -1246,7 +1279,7 @@ 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`.|
| | **Miscellaneous Behaviors** |
-| `hidden`{: #hidden-value} | 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. |
+| `hidden`{: #hidden-value} | 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. TODO - this needs to talk about `hidden` on an activating annotation, which is not a visible (painted) resource. |
{: .api-table #table-behavior}
{% include api/code_header.html %}
@@ -1309,12 +1342,6 @@ The value _MUST_ be string, which defines an RGB color. It SHOULD be a hex value
```
-### disables
-{: #disables}
-
-todo
-
-
### duration
{: #duration}
@@ -1337,12 +1364,6 @@ The value _MUST_ be a positive floating point number.
```
-### enables
-{: #enables}
-
-TODO
-
-
### exclude
{: #exclude}
@@ -1564,6 +1585,8 @@ The value of the `quantityValue` property of the Quantity _MUST_ be between 0.0
### interactionMode
{: #interactionMode}
+TODO clarify how `interactionMode` corresponds to `action`
+
A set of features that guide or limit user interaction with content within a Container that the publisher of the content would prefer the client to use when presenting the resource. This specification defines values in the table below that guide interactions with Cameras within a Scene. Other values for other Container types or specifying other interaction modes for 3D content may be defined externally as an [extension][prezi30-ldce]. For interaction modes pertaining to Cameras within a Scene, the client _SHOULD_ use `interactionMode` to determine the user experience features and approaches whereby users are permitted to change or adjust Cameras when viewing content within a Scene (e.g., orbiting around the scene or locking the user to a first-person perspective).
When more than one interaction mode is present, the client _SHOULD_ pick the first interaction mode that the client is capable of supporting.
@@ -1793,20 +1816,9 @@ Additional motivations may be added to the Annotation to further clarify the int
| ----- | ----------- |
| `painting` | Resources associated with a Container by an Annotation that has the `motivation` value `painting` _MUST_ be presented to the user as the representation of the Container. The content can be thought of as being _of_ the Container. The use of this motivation with target resources other than Containers is undefined. For example, an Annotation that has the `motivation` value `painting`, a body of an Image and the target of a Canvas is an instruction to present that Image as (part of) the visual representation of the Canvas. Similarly, a textual body is to be presented as (part of) the visual representation of the Container and not positioned in some other part of the user interface.|
| `supplementing` | Resources associated with a Container by an Annotation that has the `motivation` value `supplementing` _MAY_ be presented to the user as part of the representation of the Container, or _MAY_ be presented in a different part of the user interface. The content can be thought of as being _from_ the Container. The use of this motivation with target resources other than Containers is undefined. For example, an Annotation that has the `motivation` value `supplementing`, a body of an Image and the target of part of a Canvas is an instruction to present that Image to the user either in the Canvas's rendering area or somewhere associated with it, and could be used to present an easier to read representation of a diagram. Similarly, a textual body is to be presented either in the targeted region of the Container or otherwise associated with it, and might be OCR, a manual transcription or a translation of handwritten text, or captions for what is being said in a Timeline with audio content. |
-| `activating` | 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. An annotation with the motivation `activating` has any valid IIIF Resource, or list of IIIF resources, or references to IIIF resources as its `target` property, and any potentially interactive resource as its `body`. It indicates that a user interaction will trigger a change in a Container, or play a named animation in a Model. If the `body` of the Annotation is of type `TextualBody` and the `target` is of type `SpecificResource` with a `selector` property of type `AnimationSelector`, then the client offers a UI such that when the user selects an interactive element labelled by the TextualBody, the named animation in the model painted by the `source` is played. |
+| `activating` | 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. See [Dynamic Content]() for processing. |
{: .api-table #table-motivations}
-#### Activating Annotations
-
-The client must render the target resource as an interactive element in the user interface, which the user can trigger (e.g., clicking, selecting, entering).
-
-The `body` of the annotation is then activated. This specification defines the following client behaviors; others may me found in the [IIIF Cookbook][ref].
-
-* If the body is a reference to a Painting Annotation:
- * if the annotation has the `behavior` "hidden", then remove "hidden" from the `behavior`.
- * if the annotation paints a Camera, make that Camera the active Camera (i.e., make this the viewport) (see [ref]).
-* If the body is a SpecificResource with a `selector` property with the type "AnimationSelector", play the animation named by the `value` property of the Selector. (see [ref]).
-
### navDate
{: #navDate}
@@ -2958,6 +2970,70 @@ A number (floating point) giving the z coordinate of the point, relative to the
{ "z": 100 }
```
+## Dynamic Content
+{: #dynamic-content}
+
+TODO note that SpecificResource body `source` must exist in manifest elsewhere, is only a reference.
+
+An annotation with the motivation `activating` has any valid IIIF Resource, or list of IIIF resources, or references to IIIF resources as its `body` property, and any potentially interactable resource as its `target`. The `body` is activated by the `target`.
+
+There are two categories of activating annotation targets (interactable things):
+
+* Annotations - content of the container (a painting annotation rendered in the Scene) or content that targets the container (a commenting annotation, a map pin... which may have off-Container representations in a UI eg comments in a side panel).
+* Extents of Containers - a volume of a Scene, region of a Canvas, or interval of time in any Container with a `duration` (the client may or may not render these "hit boxes")
+
+How the client makes these interactable is client-dependent.
+
+Need to cover:
+
+Clients supporting dynamic content need to support
+
+ - non-painting annotations e.g., commenting annos (and other annos that usually have textual bodies that could be made clickable by a client, or map pin markers, etc)
+ - painted resources such as models
+ - volumes
+ - time extents
+ - other activating annos
+
+This specification defines the following client behaviors; others may be found in the [IIIF Cookbook][ref].
+
+> enables first then disables (?)
+
+breaking change
+anno `body` => Ordered List, redefine in context
+will break any `"body": {}` annos
+
+
+### Showing and hiding content
+
+If the body is a reference to a Painting Annotation or a non-painting , the client must render the `target` resource as an interactive element in the user interface, which the user (or _Container time_) can trigger (e.g., clicking, selecting, entering). The `body` of the annotation is then activated by this interaction.
+
+ * if the annotation has the `behavior` "hidden", then remove "hidden" from the `behavior`.
+
+(example: click the comment, object appears, light goes on)
+
+enables and disables
+
+### Activating Lights
+
+You can just use enables and disables
+
+### Activating Cameras
+
+ * if the annotation paints a Camera, make that Camera the active Camera (i.e., make this the viewport) (see [ref]).
+
+### Playing animations
+
+If the `body` is of type `SpecificResource` with a `selector` property of type `AnimationSelector`, the named animation in the model painted by the `source` is played when the `target` is activated.
+* If the body is a SpecificResource with a `selector` property with the type "AnimationSelector", play the animation named by the `value` property of the Selector. (see [ref]).
+
+How do you stop the animation? And if you can stop it, what happens - reset? If you activate it again, does it resume or restart?
+
+scope
+
+
+
+
+
## JSON-LD and Extensions
{: #json-ld-and-extensions}
diff --git a/source/presentation/4.0/scratch.md b/source/presentation/4.0/scratch.md
index 5ff5ad0a3..59e3b67e6 100644
--- a/source/presentation/4.0/scratch.md
+++ b/source/presentation/4.0/scratch.md
@@ -196,6 +196,26 @@ What to do about activating annos in the introduced content?
+## 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)
+
+
+## Storytelling example
+
+* Something really cool that brings a lot of things together!
+
+
+# Auth of Presentation API resources
+
+It may be necessary to restrict access to the descriptions made available via the Presentation API. As the primary means of interaction with the descriptions is by web browsers using XmlHttpRequests across domains, there are some considerations regarding the most appropriate methods for authenticating users and authorizing their access. The approach taken is described in the [Authentication][iiif-auth] specification, and requires requesting a token to add to the requests to identify the user. This token might also be used for other requests defined by other APIs.
+
+
_removed content state use case:_
@@ -229,3 +249,169 @@ What to do about activating annos in the introduced content?
}
```
+# Activating by entering (or interacting with) a volume:
+
+```json
+{
+ "id": "https://example.org/iiif/3d/anno9",
+ "type": "Annotation",
+ "motivation": ["activating"],
+ "target": [
+ {
+ "id": "https://example.org/iiif/3d/anno9",
+ "type": "SpecificResource",
+ "selector": [
+ {
+ "type": "WktSelector",
+ "wktLiteral": "POLYHEDRALSURFACE Z (blah blah)"
+ }
+ ],
+ "source": "https://example.org/iiif/3d/Scene1"
+ }
+ ],
+ "body": [
+ {
+ "type": "JSONPatch that turns on the light"
+ }
+ ]
+}
+```
+
+
+# Controlling a video that is not painted into duration (or not even painted at all)
+
+```json
+{
+ "id": "https://example.org/iiif/3d/box-opening-activating-anno",
+ "type": "Annotation",
+ "motivation": ["activating"],
+ "disables": ["https://example.org/iiif/3d/commenting-anno-for-video"],
+ "target": [
+ {
+ "id": "https://example.org/iiif/3d/third-man-from-left",
+ "type": "Annotation"
+ }
+ ],
+ "body": [
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/3d/commenting-anno-for-video",
+ "action": ["stop", "reset"]
+ }
+ ]
+}
+```
+
+# actions for disable and enable (yes)
+
+```json
+{
+ "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",
+ "body": [
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2",
+ "action": ["disable"]
+ },
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3",
+ "action": ["enable"]
+ },
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4",
+ "action": ["show"]
+ }
+ ]
+},
+```
+
+# Lightswitch enables and disables as props (no)
+
+```json
+{
+ "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"
+ ]
+},
+```
+
+# Animation with action
+
+```json
+{
+ "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"
+ }
+ ],
+ "action": ["start"]
+ }
+ ]
+}
+```
+
+# Verbose form of scope
+
+```json
+{
+ "id": "https://example.org/iiif/3d/anno9",
+ "type": "Annotation",
+ "motivation": ["activating"],
+ "target": [
+ {
+ "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth",
+ "type": "Annotation"
+ }
+ ],
+ "body": [
+ {
+ "type": "SpecificResource",
+ "source": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth",
+ "action": ["show", "enable", "select"]
+ }
+ ]
+}
+
+```
+
+...is equivalent to this on the commenting anno:
+
+```jsonc
+ "scope": [ // <= ["show", "enable", "select"]
+ {
+ "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth",
+ "type": "Annotation"
+ }
+ ],
+```
\ No newline at end of file