Skip to content

models.proto

syntax = "proto3";

option csharp_namespace = "TSS.Gateway.Sdk.Models";

// The story data structures as the player runs them, returned by the story.data query and, for
// the active scene, by scene.status. Positions and sizes are in pixels on the screen's canvas,
// origin at the bottom-left, y up. Volumes are normalized: 0 to 1.

message Story {
    string uuid = 1;
    string title = 2;
    int32 version = 3;
    string activeSceneUuid = 4;
    float volume = 5; // Master volume, 0 to 1.
    optional Screensaver screensaver = 6;
    repeated Scene scenes = 7;
    repeated Asset assets = 8;
    repeated Trigger triggers = 9;
    string integrationId = 10;
    repeated Group groups = 11;
    bool returnToLastSceneAfterScreensaver = 12; // True resumes at the scene that was active when the screensaver started; false restarts at the first scene.
    optional string backgroundColor = 13; // Hex color string, for example "#FF8800".
}

// A set of assets that stays visible across the scenes named in inScenes.
message Group {
    string uuid = 1;
    string name = 2;
    int32 baseLayer = 3; // Layer the group renders from; member asset layers stack on top of it.
    repeated string inScenes = 4;
    repeated string assets = 5;
}

message Screensaver {
    string uuid = 1; // Scene to switch to.
    int32 delay = 2; // Milliseconds without interaction before the screensaver scene activates.
}

message Scene {
    string uuid = 1;
    string title = 2;
    bool autoSwitch = 3; // True switches to the next scene automatically when the background video finishes.
    repeated string assets = 4; // Uuids of the assets in this scene.
    oneof transition {
        EffectTransition effectTransition = 5;
        CustomTransition customTransition = 6;
    };
    string integrationId = 7;
    Thumbnails thumbnails = 8;
    int32 sceneIndex = 9; // The screensaver scene is 0, the other scenes count from 1 in story order, skipping the screensaver. Without a screensaver the count still starts at 1.
}

// A transition rendered by story-authored assets instead of a built-in effect.
message CustomTransition {
    int32 duration = 1; // Milliseconds.
    repeated string assets = 2; // Uuids of the assets that make up the transition.
}

message EffectTransition {
    EffectType effectType = 1;
    int32 duration = 2; // Milliseconds.
    EaseType easeType = 3;
    float feather = 4;
    bool playPerSegment = 5; // True runs the effect per horizontal screen segment instead of over the whole screen at once.
}

// Thumbnail image paths of a story, scene, or asset.
message Thumbnails {
    string default = 1;
    string large = 2;
}

message Asset {
    string uuid = 1;
    string title = 2;
    int32 layer = 3; // Render order within the scene, higher renders on top.
    float opacity = 4; // 0 (fully transparent) to 1 (opaque).
    bool draggable = 6;
    bool roundedCorners = 7;
    bool visible = 8;
    Rectangle rectangle = 9;
    Margins margins = 10; // Applied crop, see AssetCropRequest in requests.proto.
    oneof data {
        UrlData urlData = 11;
        VideoData videoData = 12;
        TextData textData = 13;
        SoundData soundData = 14;
        PdfData pdfData = 15;
        NdiData ndiData = 16;
        ImageData imageData = 17;
    }
    string integrationId = 18;
    bool hasOnClickActions = 19;
    Thumbnails thumbnails = 20;
}

// Position and size in canvas pixels; x/y is the bottom-left corner.
message Rectangle {
    float x = 1;
    float y = 2;
    float width = 3;
    float height = 4;
}

// Crop margins in pixels, measured inward from the asset's original edges.
message Margins {
    int32 left = 1;
    int32 right = 2;
    int32 top = 3;
    int32 bottom = 4;
}

// A web page asset.
message UrlData {
    bool urlNavigation = 1;
    string url = 2;
    float volume = 3;
    optional bool back = 4;
    optional bool forward = 5;
    optional bool home = 6;
    optional bool inputFocus = 7;
    optional bool streamActive = 8;
    repeated UrlRequest requests = 9; // Pending page interactions, see the url asset requests in requests.proto.
    optional bool isMuted = 10;
    optional int32 zoom = 11; // Page zoom percentage applied as a reflowing Chromium zoom factor, 25-500. Absent or 0 means 100 (no zoom).
}

message VideoData {
    bool play = 1;
    bool loop = 3;
    bool split = 4; // True when the video is encoded as vertically stacked parts because the source is wider than 7680 pixels.
    optional float volume = 5;
    optional double progress = 6; // Playback position, 0 (start) to 1 (end).
    optional int32 duration = 7; // Milliseconds.
    optional string codec = 8;
    repeated FileData files = 9;
    optional bool isLoaded = 10;
    optional bool isMuted = 11;
    optional bool hideOnFinish = 12; // True hides the asset the moment playback finishes. Absent or false keeps the finished video on screen.
}

message TextData {
    TextHorizontalAlignment horizontalAlignment = 1;
    TextVerticalAlignment verticalAlignment = 2;
    string color = 3; // Hex color string, for example "#FF8800".
    string font = 4 [deprecated = true];
    int32 size = 5; // Font size in px, rounded to a whole number; exactSize carries the fraction.
    string text = 6;
    bool bold = 7 [deprecated = true];
    bool italic = 8 [deprecated = true];
    bool underline = 9;
    string fontFile = 10;
    float lineHeight = 11;
    repeated TextParagraph paragraphs = 12; // Styled text, one paragraph per line of the text. Empty: the whole text uses the base style above.
    optional float exactSize = 13; // Font size in px including its fraction, for example in a scaled story. When set, it is the size to render with instead of size.
}

// One line of styled text. A paragraph without runs is an empty line in the base style; an empty line in another style
// has one run without text that carries that style.
message TextParagraph {
    repeated TextRun runs = 1;
}

// A piece of text in one style. A run only sets the properties that differ from the base style of
// its TextData; a property that is not set inherits the base style.
message TextRun {
    string text = 1; // Contains no line breaks; the paragraphs separate the lines. Empty: the run only sizes its line.
    optional string fontFile = 2; // Same form as TextData.fontFile.
    optional float size = 3; // Same unit as TextData.size.
    optional string color = 4; // Hex color string, for example "#FF8800".
    optional bool underline = 5;
}

message SoundData
{
    bool play = 1;
    bool loop = 2;
    FileData file = 3;
    optional int32 duration = 4; // Milliseconds.
    optional float volume = 5;
    optional double progress = 6; // Playback position, 0 (start) to 1 (end).
    optional bool isMuted = 7;
}

message PdfData {
    int32 page = 1; // Zero-based page index.
    int32 pageCount = 2;
    FileData file = 3;
}

// An NDI (network video) source shown as an asset.
message NdiData {
    string sourceName = 1;
    bool visibleOnConnection = 2;
    float volume = 3;
    optional bool connected = 4;
    optional bool isMuted = 5;
}

message ImageData {
    repeated FileData files = 1;
}

message FileData {
    string uuid = 1;
    int32 version = 2;
    string name = 3;
    optional string path = 4;
}

message UrlRequest{
    oneof request{
        NavigationType navigation = 1;
        string key = 2;
        UrlTouch touch = 3;
        string url = 5; // Page to load, see the asset.change-url request in requests.proto.
    }
    optional bool internal = 4;
}

// A touch on a url asset's page. Coordinates are normalized to the page, 0 to 1, and clamped.
message UrlTouch{
    UrlTouchType type = 1;
    float x = 2;
    float y = 3;
    int32 touchId = 4; // Identifies the finger across start/move/end, for multi-touch gestures.
}

// A story-authored trigger; fire it with trigger.fire (requests.proto).
message Trigger {
    string uuid = 1;
    repeated Action actions = 2;
}

message Action {
    string uuid = 1;
    int32 screenId = 2;
    ActionType type = 3;
}

enum UrlTouchType {
    START = 0;
    END = 1;
    MOVE = 2;
}

enum NavigationType {
    BACK = 0;
    FORWARD = 1;
    REFRESH = 2;
    HOME = 3;
}

enum TextHorizontalAlignment {
    LEFT = 0;
    CENTER = 1;
    RIGHT = 2;
}

enum TextVerticalAlignment {
    TOP = 0;
    MIDDLE = 1;
    BOTTOM = 2;
}

enum ActionType {
    SCENE_GOTO = 0;
    ASSET_TOGGLE = 1;
    ASSET_SHOW = 2;
    ASSET_HIDE = 3;
    SCENE_NEXT = 4;
    SCENE_PREV = 5;
}

enum EffectType{
    DEFAULT = 0;
    FADE = 1;
    DIRECT = 2;
    PUSH_LEFT = 3;
    PUSH_RIGHT = 4;
    PUSH_UP = 5;
    PUSH_DOWN = 6;
    COVER_LEFT = 7;
    COVER_RIGHT = 8;
    COVER_UP = 9;
    COVER_DOWN = 10;
    UNCOVER_LEFT = 11;
    UNCOVER_RIGHT = 12;
    UNCOVER_UP = 13;
    UNCOVER_DOWN = 14;
    WIPE_LEFT = 15;
    WIPE_RIGHT = 16;
    WIPE_UP = 17;
    WIPE_DOWN = 18;
    CURTAIN_HORIZONTAL = 19;
    CURTAIN_VERTICAL = 20;
    FALL_OVER = 21;
    CUBE = 22;
    BATMAN = 23;
}

enum EaseType{
    LINEAR = 0;
    SMOOTH = 1;
    BUTTERSMOOTH = 2;
    EXTRA_BUTTERSMOOTH = 3;
    QUAD_IN = 4;
    QUAD_OUT = 5;
    QUAD_IN_OUT = 6;
    CUBIC_IN = 7;
    CUBIC_OUT = 8;
    CUBIC_IN_OUT = 9;
    QUART_IN = 10;
    QUART_OUT = 11;
    QUART_IN_OUT = 12;
    QUAD_CIRC_IN = 13;
    QUAD_CIRC_OUT = 14;
    QUAD_CIRC_IN_OUT = 15;
    CUBIC_CIRC_IN = 16;
    CUBIC_CIRC_OUT = 17;
    CUBIC_CIRC_IN_OUT = 18;
    QUART_CIRC_IN = 19;
    QUART_CIRC_OUT = 20;
    QUART_CIRC_IN_OUT = 21;
    BOUNCE_IN = 22;
    BOUNCE_OUT = 23;
    BOUNCE_IN_OUT = 24;
    ELASTIC_IN = 25;
    ELASTIC_OUT = 26;
    ELASTIC_IN_OUT = 27;
    ASYNC_SMOOTH = 28;
}