Skip to content

Commit

Permalink
Add otio string deserialization
Browse files Browse the repository at this point in the history
Signed-off-by: Éloïse Brosseau <[email protected]>
  • Loading branch information
eloisebrosseau committed Oct 10, 2024
1 parent edf75b4 commit 69eda0b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/rv-packages/rv-otio-reader.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The RV package is installed in the usual Python package installation location: `
The package also uses a number of files located in `Plugins/SupportFiles/otio_reader` and detailed below.

- `manifest.json`: Provides examples of schemas and hooks used in the import process.
- `annotation_schema.py` An example schema of an annotation.
- `cdlExportHook.py`: An example of exporting an RVLinearize to a custom CDL effect in OTIO.
- `cdlHook.py`: An example of importing a custom CDL effect in OTIO into an RVLinearize node.
- `cdlSchema.py` An example schema of a CDL effect.
Expand Down
10 changes: 9 additions & 1 deletion src/plugins/rv-packages/otio_reader/PACKAGE
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ modes:
files:
- file: manifest.json
location: SupportFiles/$PACKAGE
- file: annotation_schema.py
location: SupportFiles/$PACKAGE
- file: cdlSchema.py
location: SupportFiles/$PACKAGE
- file: cdlHook.py
Expand Down Expand Up @@ -83,6 +85,13 @@ description: |
</p>
</li>

<li>
<p>
annotation_schema.py
An example schema of an annotation.
</p>
</li>

<li>
<p>
cdlHook.py
Expand Down Expand Up @@ -260,4 +269,3 @@ description: |
<p>
For pre- and post- hooks, no return value is expected.
</p>

59 changes: 59 additions & 0 deletions src/plugins/rv-packages/otio_reader/annotation_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# *****************************************************************************
# Copyright 2024 Autodesk, Inc. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# *****************************************************************************

"""
For our OTIO output to effectively interface with other programs
using the OpenTimelineIO Python API, our custom schema need to be
specified and registered with the API.
As per OTIO documentation, a class such as this one must be created,
the schema must be registered with a PluginManifest, and the path to that
manifest must be added to $OTIO_PLUGIN_MANIFEST_PATH; then the schema
is ready to be used.
Example:
myObject = otio.schemadef.Annotation.Annotation(name, visible, layers)
"""

import opentimelineio as otio


@otio.core.register_type
class Annotation(otio.schema.Effect):
"""A schema for annotations."""

_serializable_label = "Annotation.1"
_name = "Annotation"

def __init__(
self, name: str = "", visible: bool = True, layers: list | None = None
) -> None:
super().__init__(name=name, effect_name="Annotation.1")
self.visible = visible
self.layers = layers

_visible = otio.core.serializable_field(
"visible", required_type=bool, doc=("Visible: expects either true or false")
)

_layers = otio.core.serializable_field(
"layers", required_type=list, doc=("Layers: expects a list of annotation types")
)

@property
def layers(self) -> list:
return self._layers

@layers.setter
def layers(self, val: list):
self._layers = val

def __str__(self) -> str:
return f"Annotation({self.name}, {self.effect_name}, {self.visible}, {self.layers})"

def __repr__(self) -> str:
return f"otio.schema.Annotation(name={self.name!r}, effect_name={self.effect_name!r}, visible={self.visible!r}, layers={self.layers!r})"
6 changes: 6 additions & 0 deletions src/plugins/rv-packages/otio_reader/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
{
"OTIO_SCHEMA" : "PluginManifest.1",
"schemadefs" : [
{
"OTIO_SCHEMA" : "SchemaDef.1",
"name" : "Annotation",
"execution_scope" : "in process",
"filepath" : "annotation_schema.py"
},
{
"OTIO_SCHEMA" : "SchemaDef.1",
"name" : "CDL",
Expand Down
25 changes: 23 additions & 2 deletions src/plugins/rv-packages/otio_reader/otio_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,24 @@ class NoNodeFromHook(otio.exceptions.OTIOError):
pass


def read_otio_string(otio_string: str, host_prefix: str | None = None) -> object | None:
"""
Main entry point to expand a given otio string into the current RV session.
Returns the top level node created that represents this otio
timeline.
"""
otio_obj = otio.adapters.read_from_string(otio_string)
timeline = otio_obj["otio"]

if host_prefix is not None:
context = {"sg_url": host_prefix}
else:
context = None

return create_rv_node_from_otio(timeline, context)


def read_otio_file(otio_file):
"""
Main entry point to expand a given otio (or file otio can read)
Expand Down Expand Up @@ -276,7 +294,7 @@ def _create_track(in_seq, context=None):
return new_seq


def _get_global_transform(tl):
def _get_global_transform(tl) -> dict:
# since there's no global scale in otio, calculate the minimum box size
# that can contain all clips
def find_display_bounds(tl):
Expand Down Expand Up @@ -491,9 +509,12 @@ def add_media(media_ref, active_key, cmd, *cmd_args):
return source_group, active_source


def _get_media_path(target_url, context=None):
def _get_media_path(target_url: str, context: dict | None = None) -> str:
context = context or {}

if "sg_url" in context:
return context.get("sg_url") + target_url

if not os.path.isabs(target_url):
# if this is a relative file path, assume relative to the otio file
otio_path = context.get("otio_file")
Expand Down

0 comments on commit 69eda0b

Please sign in to comment.