From 59b770d820824d7a75fa1b9c54b95bb72728c8d4 Mon Sep 17 00:00:00 2001 From: Wojciech Kozyra Date: Thu, 7 Dec 2023 11:22:50 +0100 Subject: [PATCH] [docs] Update `Component` docs + explain main concepts (#289) --- .gitignore | 2 - compositor_render/src/scene/components.rs | 8 +- .../src/scene/rescaler_component.rs | 4 +- .../src/scene/rescaler_component/layout.rs | 6 +- .../src/scene/tiles_component.rs | 8 +- .../src/scene/tiles_component/layout.rs | 4 +- docs/pages/api/components/Image.md | 14 ++ docs/pages/api/components/InputStream.md | 15 ++ docs/pages/api/components/Rescaler.md | 23 +++ docs/pages/api/components/Shader.md | 14 ++ docs/pages/api/components/Text.md | 10 ++ docs/pages/api/components/Tiles.md | 28 +++ docs/pages/api/components/View.md | 37 ++++ docs/pages/api/components/WebView.md | 18 ++ docs/pages/api/renderers/image.md | 5 + docs/pages/api/renderers/shader.md | 4 + docs/pages/api/renderers/web.md | 5 + docs/pages/concept/component.md | 63 +++++++ docs/pages/concept/layouts.md | 42 +++++ docs/pages/concept/shaders.md | 128 ++++++++++++++ docs/sidebars.ts | 8 +- schemas/register.schema.json | 28 --- schemas/scene.schema.json | 119 ++++++++----- .../align_center_with_03_inputs.scene.json | 4 +- .../align_top_left_with_03_inputs.scene.json | 4 +- ...rgin_and_padding_with_03_inputs.scene.json | 4 +- src/bin/generate_docs/main.rs | 9 +- src/types/component.rs | 166 ++++++++++-------- src/types/from_component.rs | 15 +- src/types/from_renderer.rs | 10 +- src/types/renderer.rs | 2 - src/types/util.rs | 1 + 32 files changed, 613 insertions(+), 195 deletions(-) create mode 100644 docs/pages/api/components/Image.md create mode 100644 docs/pages/api/components/InputStream.md create mode 100644 docs/pages/api/components/Rescaler.md create mode 100644 docs/pages/api/components/Shader.md create mode 100644 docs/pages/api/components/Text.md create mode 100644 docs/pages/api/components/Tiles.md create mode 100644 docs/pages/api/components/View.md create mode 100644 docs/pages/api/components/WebView.md create mode 100644 docs/pages/api/renderers/image.md create mode 100644 docs/pages/api/renderers/web.md create mode 100644 docs/pages/concept/component.md create mode 100644 docs/pages/concept/layouts.md create mode 100644 docs/pages/concept/shaders.md diff --git a/.gitignore b/.gitignore index 2c5d1603b..3d72bb164 100644 --- a/.gitignore +++ b/.gitignore @@ -28,8 +28,6 @@ target/ # Generated during runtime /shmem /failed_snapshot_tests -# TODO: /components will be removed in the near future (next PR). -/docs/pages/api/components /docs/pages/api/generated /video_compositor.app diff --git a/compositor_render/src/scene/components.rs b/compositor_render/src/scene/components.rs index efc7055d2..12208da80 100644 --- a/compositor_render/src/scene/components.rs +++ b/compositor_render/src/scene/components.rs @@ -195,13 +195,13 @@ pub struct RescalerComponent { pub position: Position, pub transition: Option, - pub mode: ResizeMode, + pub mode: RescaleMode, pub horizontal_align: HorizontalAlign, pub vertical_align: VerticalAlign, } #[derive(Debug, Clone, Copy)] -pub enum ResizeMode { +pub enum RescaleMode { Fit, Fill, } @@ -218,6 +218,6 @@ pub struct TilesComponent { pub tile_aspect_ratio: (u32, u32), pub margin: f32, pub padding: f32, - pub horizontal_alignment: HorizontalAlign, - pub vertical_alignment: VerticalAlign, + pub horizontal_align: HorizontalAlign, + pub vertical_align: VerticalAlign, } diff --git a/compositor_render/src/scene/rescaler_component.rs b/compositor_render/src/scene/rescaler_component.rs index 1098089db..9ade89534 100644 --- a/compositor_render/src/scene/rescaler_component.rs +++ b/compositor_render/src/scene/rescaler_component.rs @@ -9,7 +9,7 @@ use crate::transformations::layout::NestedLayout; use super::{ components::RescalerComponent, layout::StatefulLayoutComponent, scene_state::BuildStateTreeCtx, - Component, ComponentId, IntermediateNode, Position, ResizeMode, SceneError, Size, + Component, ComponentId, IntermediateNode, Position, RescaleMode, SceneError, Size, StatefulComponent, Transition, }; @@ -30,7 +30,7 @@ struct RescalerComponentParam { id: Option, position: Position, - mode: ResizeMode, + mode: RescaleMode, horizontal_align: HorizontalAlign, vertical_align: VerticalAlign, } diff --git a/compositor_render/src/scene/rescaler_component/layout.rs b/compositor_render/src/scene/rescaler_component/layout.rs index 40c4cb145..f02177afe 100644 --- a/compositor_render/src/scene/rescaler_component/layout.rs +++ b/compositor_render/src/scene/rescaler_component/layout.rs @@ -3,7 +3,7 @@ use std::time::Duration; use compositor_common::util::align::{HorizontalAlign, VerticalAlign}; use crate::{ - scene::{layout::StatefulLayoutComponent, ResizeMode, Size, StatefulComponent}, + scene::{layout::StatefulLayoutComponent, RescaleMode, Size, StatefulComponent}, transformations::layout::{Crop, LayoutContent, NestedLayout}, }; @@ -28,10 +28,10 @@ impl RescalerComponentParam { } (Some(child_width), Some(child_height)) => { let scale = match self.mode { - ResizeMode::Fit => { + RescaleMode::Fit => { f32::min(size.width / child_width, size.height / child_height) } - ResizeMode::Fill => { + RescaleMode::Fill => { f32::max(size.width / child_width, size.height / child_height) } }; diff --git a/compositor_render/src/scene/tiles_component.rs b/compositor_render/src/scene/tiles_component.rs index 1e232561b..ac8fded6e 100644 --- a/compositor_render/src/scene/tiles_component.rs +++ b/compositor_render/src/scene/tiles_component.rs @@ -31,8 +31,8 @@ struct TilesComponentParams { tile_aspect_ratio: (u32, u32), margin: f32, padding: f32, - horizontal_alignment: HorizontalAlign, - vertical_alignment: VerticalAlign, + horizontal_align: HorizontalAlign, + vertical_align: VerticalAlign, } impl StatefulTilesComponent { @@ -93,8 +93,8 @@ impl TilesComponent { tile_aspect_ratio: self.tile_aspect_ratio, margin: self.margin, padding: self.padding, - horizontal_alignment: self.horizontal_alignment, - vertical_alignment: self.vertical_alignment, + horizontal_align: self.horizontal_align, + vertical_align: self.vertical_align, }, children: self .children diff --git a/compositor_render/src/scene/tiles_component/layout.rs b/compositor_render/src/scene/tiles_component/layout.rs index 9e9ec7553..243c34c94 100644 --- a/compositor_render/src/scene/tiles_component/layout.rs +++ b/compositor_render/src/scene/tiles_component/layout.rs @@ -158,7 +158,7 @@ impl TilesComponentParams { - (tile_size.height + 2.0 * self.padding) * rows_cols.rows as f32 - (self.margin * (rows_cols.rows as f32 + 1.0)); - let (additional_top_padding, justified_padding_y) = match self.vertical_alignment { + let (additional_top_padding, justified_padding_y) = match self.vertical_align { VerticalAlign::Top => (0.0, 0.0), VerticalAlign::Center => (additional_y_padding / 2.0, 0.0), VerticalAlign::Bottom => (additional_y_padding, 0.0), @@ -180,7 +180,7 @@ impl TilesComponentParams { - (tile_size.width + 2.0 * self.padding) * tiles_in_row as f32 - (self.margin * (tiles_in_row as f32 + 1.0)); - let (additional_left_padding, justified_padding_x) = match self.horizontal_alignment { + let (additional_left_padding, justified_padding_x) = match self.horizontal_align { HorizontalAlign::Left => (0.0, 0.0), HorizontalAlign::Right => (additional_x_padding, 0.0), HorizontalAlign::Justified => { diff --git a/docs/pages/api/components/Image.md b/docs/pages/api/components/Image.md new file mode 100644 index 000000000..43e66916e --- /dev/null +++ b/docs/pages/api/components/Image.md @@ -0,0 +1,14 @@ +--- +sidebar_position: 7 +--- +import Docs from "@site/pages/api/generated/component-Image.md" + +# Image + +A component for rendering images. + +:::note +To use this component, you need to first register the image with matching `image_id` using [`RegisterRenderer`](../routes#register-renderer) request. +::: + + diff --git a/docs/pages/api/components/InputStream.md b/docs/pages/api/components/InputStream.md new file mode 100644 index 000000000..d6844c1a7 --- /dev/null +++ b/docs/pages/api/components/InputStream.md @@ -0,0 +1,15 @@ +--- +sidebar_position: 1 +--- + +import Docs from "@site/pages/api/generated/component-InputStream.md" + +# InputStream + +`InputStream` represents an incoming RTP stream. + +:::note +To use this component, you need to first register the stream with matching `input_id` using [`RegisterInputStream`](../routes#register-input-stream) request. +::: + + diff --git a/docs/pages/api/components/Rescaler.md b/docs/pages/api/components/Rescaler.md new file mode 100644 index 000000000..995b5c1ae --- /dev/null +++ b/docs/pages/api/components/Rescaler.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +--- +import Docs from "@site/pages/api/generated/component-Rescaler.md" + +# Rescaler + +`Rescaler` is a layout component responsible for rescaling other components. + +### Absolute positioning + +A component is absolutely positioned if it defines fields like `top`, `left`, `right`, `bottom`, or `rotation`. +Those fields define the component's position relative to its parent. However, to respect those +values, the parent component has to be a layout component that supports absolute positioning. + +- `Rescaler` **does not** support absolute positioning for its child components. All children will still be rendered, but all fields like `top`, `left`, `right`, `bottom`, and `rotation` will be ignored. +- `Rescaler` can be absolutely positioned relative to its parent, if the parent component supports it. + +### Static positioning + +`Rescaler` always have exactly one child that will be proportionally rescaled to match the parent. + + diff --git a/docs/pages/api/components/Shader.md b/docs/pages/api/components/Shader.md new file mode 100644 index 000000000..60cc7cf1b --- /dev/null +++ b/docs/pages/api/components/Shader.md @@ -0,0 +1,14 @@ +--- +sidebar_position: 6 +--- +import Docs from "@site/pages/api/generated/component-Shader.md" + +# Shader + +`Shader` applies transformation defined via WGSL shader on its children. [Learn more.](../../concept/shaders) + +:::note +To use this component, you need to first register the shader with matching `shader_id` using [`RegisterRenderer`](../routes#register-renderer) request. +::: + + diff --git a/docs/pages/api/components/Text.md b/docs/pages/api/components/Text.md new file mode 100644 index 000000000..ce8aa8189 --- /dev/null +++ b/docs/pages/api/components/Text.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 5 +--- +import Docs from "@site/pages/api/generated/component-Text.md" + +# Text + +A component for rendering text. + + diff --git a/docs/pages/api/components/Tiles.md b/docs/pages/api/components/Tiles.md new file mode 100644 index 000000000..f05413b5c --- /dev/null +++ b/docs/pages/api/components/Tiles.md @@ -0,0 +1,28 @@ +--- +sidebar_position: 4 +--- +import Docs from "@site/pages/api/generated/component-Tiles.md" + +# Tiles + +`Tiles` is a layout component that places all the child components next to each other while maximizing the use of available space. The component divides its area into multiple rectangles/tiles, one for each child component. All of those rectangles are the same size and do not overlap over each other. + +### Absolute positioning + +- `Tiles` **does not** support absolute positioning for its child components. All children will still be rendered, but all fields like `top`, `left`, `right`, `bottom`, and `rotation` will be ignored. +- `Tiles` **can not** be absolutely positioned relative to it's parent. + +### Static positioning + +The component calculates the number of rows and columns that children should be divided into. The result is based on: +- The size of the `Tiles` component. +- Aspect ratio of a single tile (`tile_aspect_ratio` field). +- Number of children components. + +An optimal number of rows and columns should result in a layout that covers the biggest part of its area. Children components are placed based on their order, from left to right, and row-by-row from top to bottom. + +When placing a child component inside a tile, the component might change its size. +- Non-layout component scales proportionally to fit inside the parent. If the aspect ratios of a child and its parent do not match, then the component will be centered vertically or horizontally. +- Layout component takes the `width` and `height` of a tile. It ignores its own `width`/`height` fields if they are defined. + + diff --git a/docs/pages/api/components/View.md b/docs/pages/api/components/View.md new file mode 100644 index 000000000..43d3b8911 --- /dev/null +++ b/docs/pages/api/components/View.md @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- +import Docs from "@site/pages/api/generated/component-View.md" + +# View + +`View` is the compositor's core layout mechanism. Its role is analogous to the +`
` tag in HTML. It provides a container with basic styling that can be further composed. + +### Absolute positioning + +A component is absolutely positioned if it defines fields like `top`, `left`, `right`, `bottom`, or `rotation`. +Those fields define the component's position relative to its parent. However, to respect those +values, the parent component has to be a layout component that supports absolute positioning. + +- `View` supports absolute positioning for its child components. +- `View` can be absolutely positioned relative to its parent if the parent component supports it. + +### Static positioning + +When children of a `View` component have a static position, they are placed next to each other. + +#### For `direction=row`: + +Children of a `View` component form a row, with items aligned to the top. The size of each child will be calculated in the following way: +- If the `width` or `height` of a child component is defined, then those values take priority. +- If the `height` is not defined, the component will have the same `height` as its parent. +- If the `width` is not defined, we calculate the sum `width` of all components with that value defined. + - If it is larger than the parent's `width`, then the `width` of the rest of the components is zero. + - If it is smaller than the parent's `width`, calculate the difference and divide the resulting value equally between all children with unknown widths. + +#### For `direction=column`: + +Analogous to the `direction=row` case, but children form a column instead, with items aligned to the left. + + diff --git a/docs/pages/api/components/WebView.md b/docs/pages/api/components/WebView.md new file mode 100644 index 000000000..49258948a --- /dev/null +++ b/docs/pages/api/components/WebView.md @@ -0,0 +1,18 @@ +--- +sidebar_position: 8 +--- +import Docs from "@site/pages/api/generated/component-WebView.md" + +# WebView + +`WebView` renders a website using Chromium engine embedded inside the compositor. + +:::note +To use this component, you need to first register the web renderer instance with matching `instance_id` using [`RegisterRenderer`](../routes#register-renderer) request. +::: + +:::warning +Only one component can use specific `instance_id` at the time. +::: + + diff --git a/docs/pages/api/renderers/image.md b/docs/pages/api/renderers/image.md new file mode 100644 index 000000000..0fc877beb --- /dev/null +++ b/docs/pages/api/renderers/image.md @@ -0,0 +1,5 @@ +import Docs from "@site/pages/api/generated/renderer-Image.md" + +# Image + + diff --git a/docs/pages/api/renderers/shader.md b/docs/pages/api/renderers/shader.md index c2e7c8d4c..2d8fdc1ef 100644 --- a/docs/pages/api/renderers/shader.md +++ b/docs/pages/api/renderers/shader.md @@ -1 +1,5 @@ +import Docs from "@site/pages/api/generated/renderer-Shader.md" + # Shader + + diff --git a/docs/pages/api/renderers/web.md b/docs/pages/api/renderers/web.md new file mode 100644 index 000000000..0cf7fc743 --- /dev/null +++ b/docs/pages/api/renderers/web.md @@ -0,0 +1,5 @@ +import Docs from "@site/pages/api/generated/renderer-WebRenderer.md" + +# Web Renderer + + diff --git a/docs/pages/concept/component.md b/docs/pages/concept/component.md new file mode 100644 index 000000000..d4a5789ae --- /dev/null +++ b/docs/pages/concept/component.md @@ -0,0 +1,63 @@ +# Component + +A component is a basic block used to define how video streams are composed. + +## Layout Components + +Layout component is a type of component responsible for defining the size and position of other components. + +Currently, we support the following layout components: +- [View](../api/components/View) +- [Tiles](../api/components/Tiles) +- [Rescaler](../api/components/Rescaler) + +Learn more about layouts [here](./layouts). + +## Non-layout components + +Non-layout components have their unique behaviors. In most cases, they do not support or interact with mechanisms introduced by layouts. Sometimes, they even override the behavior of other components. + +For example, if you create a `Shader` component with a `View` component as its child, the properties like `width`, `top`, `rotation` ..., will be ignored. A `Shader` component, when rendering, receives all its children as GPU textures. It will just execute whatever the user-provided shader source implements without applying any layout properties that component might have. + +## Scene + +Component tree that represents what will be rendered for a specific output. + +Example scene: +```typescript +{ + "outputs": [ + { + "output_id": "example_output_1" + "root": { + "type": "view", + "background_color_rgba": "#0000FFFF" + "children": [ + { + "type": "input-stream", + "input_id": "example_input_1", + } + ] + } + } + ] +} +``` + +In the example above, we define a scene for a single output `example_output_1` where an input stream `example_input_1` is rendered inside a [`View` component](../api/components/View). + +:::note +You need to register `"example_output_1"` and `"example_input_1"` before using them in the scene definition. +::: + +### Renderers + +Renderers are entities capable of producing frames (in some cases based on some provided input). The renderer could be a WGSL shader, web renderer instance, or an image. They are not directly part of the scene definition. Instead, components are using them as part of their internal implementation. + +For example: +- [The `Shader` component](../api/components/Shader) has a field `shader_id` that identifies a [`Shader` renderer](../api/renderers/Shader). +- [The `Image` component](../api/components/Image) has a field `image_id` that identifies an [`Image` renderer](../api/renderers/Image). + +Every renderer, except [`WebRenderer`](../api/renderers/web), can be used in multiple components. For example, you can create a single `Shader` renderer that applies some effect and use that `shader_id` in multiple `Shader` components. + + diff --git a/docs/pages/concept/layouts.md b/docs/pages/concept/layouts.md new file mode 100644 index 000000000..57cfdf103 --- /dev/null +++ b/docs/pages/concept/layouts.md @@ -0,0 +1,42 @@ +# Layouts + +Layout components define the size, position, and simple styling of other components. + +Currently, we support the following layout components: +- [View](../api/components/View) +- [Tiles](../api/components/Tiles) +- [Rescaler](../api/components/Rescaler) + +## Common properties + +Most layout components share a set of common properties. + +- `width` - Width of a component in pixels. +- `height` - Height of a component in pixels. + +### Absolute positioning properties + +When a component is positioned absolutely, it will ignore the normal layout of its parent. + +Common properties that imply the component will be absolutely positioned: + +- `top` - Distance in pixels between this component's top edge and its parent's top edge. +- `bottom` - Distance in pixels between this component's bottom edge and its parent's bottom edge. +- `left` - Distance in pixels between this component's left edge and its parent's left edge. +- `right` - Distance in pixels between this component's right edge and its parent's right edge. +- `rotation` - Rotation in degrees. + +:::warn +Not all components support everything listed above. Consult the API reference for each component to verify it. +::: + +### Size + +The size of a layout component is defined by its parent: +- If a layout component is a root in a component tree, then its size is based on the declared resolution of an output stream. +- If a layout component is a child of a non-layout component, then it has to have its size defined, usually via the `width`/`height` fields. +- If a layout component is a child of another layout component, then, unless explicitly defined, its size will be based on the area defined by its parent. For example: + - For the `Tails` component, it will be an area of a single tile. + - For the `View` component, it will be an area calculated based on the sizes of other sibling components. + + diff --git a/docs/pages/concept/shaders.md b/docs/pages/concept/shaders.md new file mode 100644 index 000000000..7c51542cd --- /dev/null +++ b/docs/pages/concept/shaders.md @@ -0,0 +1,128 @@ +# Shaders + +Shaders are small programs that we send to a GPU to perform some computation for us. They are used extensively in the video compositor. All builtin transformation are implemented as shaders under the hood. It is also possible to create render nodes that run a custom shader on their input. Since video compositor is implemented using wgpu, the shaders have to be written in WGSL (WebGPU Shading Language). They also have to fulfill some custom requirements that allow them to be run by the video compositor. + +## General concepts + +There are two kinds of shaders that are used in the video compositor: vertex shaders and fragment shaders. + +### Vertex shaders + +Vertex shaders receive the data of a single vertex as input. It can manipulate them to make them form the shape we want to see as the output. + +The videos are represented in vertex shaders as two triangles, aligned like so: + +``` + ______ +| /| +| / | +| / | +| / | +| / | +|______| +``` + +The rectangle formed by these triangles spans the whole clip space, i.e. [-1, 1] X [-1, 1]. + +Each video passed in as input gets a separate rectangle, with the field `texture_id` describing which video this is. + +Since the compositor doesn't deal with complex geometry and most positioning/resizing/cropping should be taken care of by [builtin transformations](https://github.com/membraneframework/video_compositor/wiki/API-%E2%80%90-nodes#built-in-transformations), we don't expect the users to write nontrivial vertex shaders very often. For just applying some effects to the video, fragment shaders are the way to go. This vertex shader should take care of most of your needs (for transformations that receive a single video and only process it in the fragment shader): + +```wgsl +struct VertexOutput { + @builtin(position) position: vec4, + @location(0) tex_coords: vec2, +} + +@vertex +fn vs_main(input: VertexInput) -> VertexOutput { + var output: VertexOutput; + + output.position = vec4(input.position, 1.0); + output.tex_coords = input.tex_coords; + + return output; +} +``` + +### Fragment shaders + +A single instance of a fragment shader is started for each pixel of the output texture. That instance is responsible for calculating the color of the pixel. The return type of a fragment shader has to be a 4-element long vector of `f32`s ranging from 0.0 to 1.0. These floats are the RGBA values of the pixel. + +The fragment shader often receives texture coordinates, which describe where to sample the provided texture to get the color value corresponding to the pixel we're calculating at the moment. The texture can be sampled using the builtin `textureSample` function. The sampler that should be used for sampling the texture is provided in the header is called `sampler_` + +```wgsl +let color = textureSample(texture, sampler_, texture_coordinates) +``` + +For example see this simple fragment shader, which applies the negative effect: + +```wgsl +struct VertexOutput { + @builtin(position) position: vec4, + @location(0) tex_coords: vec2, +} + +@fragment +fn fs_main(input: VertexOutput) -> @location(0) vec4 { + let color = textureSample(textures[0], sampler_, input.tex_coords); + return vec4(vec3(1.0) - color, 1.0); +} +``` + +## API + +### Header + +Every user-provided shader should include the code below. + +```wgsl +struct VertexInput { + @location(0) position: vec3, + @location(1) tex_coords: vec2, + @location(2) texture_id: i32, +} + +struct CommonShaderParameters { + time: f32, + texture_count: u32, + output_resolution: vec2, +} + +@group(0) @binding(0) var textures: binding_array, 16>; +@group(2) @binding(0) var sampler_: sampler; + +var common_params: CommonShaderParameters; +``` + +### Custom parameters + +You can define a custom WGSL struct and bind a value of this type as + +```wgsl +@group(1) @binding(0) var custom_name: CustomStruct; +``` + +This struct has to be provided when creating a node using the `shader_params` field of the [shader node struct](https://github.com/membraneframework/video_compositor/wiki/API-%E2%80%90-nodes#shader) + +### Entrypoints + +The vertex shader entrypoint has to have the following signature: + +```wgsl +@vertex +fn vs_main(input: VertexInput) -> A +``` + +Where `A` can be any user-defined struct suitable for a vertex shader output. + +The fragment shader entrypoint has to have the following signature: + +```wgsl +@fragment +fn fs_main(input: A) -> @location(0) vec4 +``` + +Where `A` is the output type of the vertex shader. + +Shaders have to be registered using the [register shader](https://github.com/membraneframework/video_compositor/wiki/Api-%E2%80%90-renderers#shader) request before they can be used. diff --git a/docs/sidebars.ts b/docs/sidebars.ts index ef0d7f568..2f2ce8f73 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -13,6 +13,12 @@ const sidebars: SidebarsConfig = { id: 'get-started', }, }, + { + type: 'category', + label: 'Concepts', + collapsible: false, + items: ['concept/component', 'concept/layouts', 'concept/shaders'], + }, { type: 'category', label: 'API Reference', @@ -48,7 +54,7 @@ const sidebars: SidebarsConfig = { label: 'Renderers', collapsible: false, description: 'Resources that need to be registered first before they can be used.', - items: ['api/renderers/shader'], + items: ['api/renderers/shader', 'api/renderers/image', 'api/renderers/web'], }, ], }, diff --git a/schemas/register.schema.json b/schemas/register.schema.json index f7d470061..81915c673 100644 --- a/schemas/register.schema.json +++ b/schemas/register.schema.json @@ -79,16 +79,6 @@ }, "source": { "type": "string" - }, - "fallback_strategy": { - "anyOf": [ - { - "$ref": "#/definitions/FallbackStrategy" - }, - { - "type": "null" - } - ] } } }, @@ -125,16 +115,6 @@ "type": "null" } ] - }, - "fallback_strategy": { - "anyOf": [ - { - "$ref": "#/definitions/FallbackStrategy" - }, - { - "type": "null" - } - ] } } }, @@ -362,14 +342,6 @@ "RendererId": { "type": "string" }, - "FallbackStrategy": { - "type": "string", - "enum": [ - "never_fallback", - "fallback_if_all_inputs_missing", - "fallback_if_any_input_missing" - ] - }, "WebEmbeddingMethod": { "type": "string", "enum": [ diff --git a/schemas/scene.schema.json b/schemas/scene.schema.json index 4ba4540d8..5e2c40bbd 100644 --- a/schemas/scene.schema.json +++ b/schemas/scene.schema.json @@ -21,7 +21,6 @@ "Component": { "oneOf": [ { - "description": "Component representing incoming RTP stream. Specific streams can be identified by an `input_id` that was part of a `RegisterInputStream` request.", "type": "object", "required": [ "input_id", @@ -35,6 +34,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -45,7 +45,12 @@ ] }, "input_id": { - "$ref": "#/definitions/InputId" + "description": "Id of an input. It identifies a stream registered using a [`RegisterInputStream`](../routes#register-input-stream) request.", + "allOf": [ + { + "$ref": "#/definitions/InputId" + } + ] } }, "additionalProperties": false @@ -63,6 +68,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -73,6 +79,7 @@ ] }, "children": { + "description": "List of component's children.", "type": [ "array", "null" @@ -98,7 +105,7 @@ "format": "float" }, "direction": { - "description": "Direction defines how static children are positioned inside the View component. \"row\" - Children positioned from left to right. \"column\" - Children positioned from top to bottom.", + "description": "Direction defines how static children are positioned inside a View component.\n\n- `\"row\"` - Children positioned from left to right.\n\n- `\"column\"` - Children positioned from top to bottom.", "anyOf": [ { "$ref": "#/definitions/ViewDirection" @@ -109,7 +116,7 @@ ] }, "top": { - "description": "Distance between the top edge of this component and the top edge of its parent. If this field is defined, then component will ignore a layout defined by its parent.", + "description": "Distance in pixels between this component's top edge and its parent's top edge. If this field is defined, then the component will ignore a layout defined by its parent.", "type": [ "number", "null" @@ -117,7 +124,7 @@ "format": "float" }, "left": { - "description": "Distance between the left edge of this component and the left edge of its parent. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Distance in pixels between this component's left edge and its parent's left edge. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -125,7 +132,7 @@ "format": "float" }, "bottom": { - "description": "Distance between the bottom edge of this component and the bottom edge of its parent. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Distance in pixels between the bottom edge of this component and the bottom edge of its parent. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -133,7 +140,7 @@ "format": "float" }, "right": { - "description": "Distance between the right edge of this component and the right edge of its parent. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Distance in pixels between this component's right edge and its parent's right edge. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -141,7 +148,7 @@ "format": "float" }, "rotation": { - "description": "Rotation of a component in degrees. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Rotation of a component in degrees. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -149,7 +156,7 @@ "format": "float" }, "transition": { - "description": "Defines how this component will behave during a scene update. This will only have an effect if previous scene already contained a View component with the same id.", + "description": "Defines how this component will behave during a scene update. This will only have an effect if the previous scene already contained a View component with the same id.", "anyOf": [ { "$ref": "#/definitions/Transition" @@ -160,7 +167,7 @@ ] }, "overflow": { - "description": "(default=\"hidden\") Controls what happens to content that is too big to fit into an area.", + "description": "(default=`\"hidden\"`) Controls what happens to content that is too big to fit into an area.", "anyOf": [ { "$ref": "#/definitions/Overflow" @@ -171,7 +178,7 @@ ] }, "background_color_rgba": { - "description": "(default=\"#00000000\") Background color in a \"#RRGGBBAA\" format.", + "description": "(default=`\"#00000000\"`) Background color in a `\"#RRGGBBAA\"` format.", "anyOf": [ { "$ref": "#/definitions/RGBAColor" @@ -199,6 +206,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -209,6 +217,7 @@ ] }, "children": { + "description": "List of component's children.", "type": [ "array", "null" @@ -218,7 +227,7 @@ } }, "instance_id": { - "description": "ID of a previously registered `WebRenderer`.\n\n

\n\n:::warning\n\nYou can only refer to specific instance in one Component at the time.\n\n:::", + "description": "Id of a web renderer instance. It identifies an instance registered using a [`RegisterRenderer`](../routes#register-renderer) request.\n\n

\n\n:::warning\n\nYou can only refer to specific instances in one Component at a time.\n\n:::", "allOf": [ { "$ref": "#/definitions/RendererId" @@ -243,6 +252,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -253,6 +263,7 @@ ] }, "children": { + "description": "List of component's children.", "type": [ "array", "null" @@ -262,7 +273,7 @@ } }, "shader_id": { - "description": "ID of a previously registered Shader.", + "description": "Id of a shader. It identifies a shader registered using a [`RegisterRenderer`](../routes#register-renderer) request.", "allOf": [ { "$ref": "#/definitions/RendererId" @@ -270,7 +281,7 @@ ] }, "shader_param": { - "description": "Object that will be serialized into a `struct` and passed inside the shader as:\n\n

\n\n```wgsl\n\n@group(1) @binding(0) var\n\n```\n\nNote: This object's structure must match the structure defined in a shader source code.", + "description": "Object that will be serialized into a `struct` and passed inside the shader as:\n\n

\n\n```wgsl\n\n@group(1) @binding(0) var\n\n```\n\n:::note\n\nThis object's structure must match the structure defined in a shader source code.\n\n:::", "anyOf": [ { "$ref": "#/definitions/ShaderParam" @@ -305,6 +316,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -315,7 +327,7 @@ ] }, "image_id": { - "description": "ID of a previously registered Image.", + "description": "Id of an image. It identifies an image registered using a [`RegisterRenderer`](../routes#register-renderer) request.", "allOf": [ { "$ref": "#/definitions/RendererId" @@ -340,6 +352,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -353,7 +366,7 @@ "type": "string" }, "width": { - "description": "Width of a texture that text will be rendered on. If not provided the resulting texture will be sized based on the defined text, but limited to `max_width` value.", + "description": "Width of a texture that text will be rendered on. If not provided, the resulting texture will be sized based on the defined text but limited to `max_width` value.", "type": [ "number", "null" @@ -361,7 +374,7 @@ "format": "float" }, "height": { - "description": "Height of a texture that text will be rendered on. If not provided the resulting texture will be sized based on the defined text, but limited to `max_width` value.\n\nIt's an error to provide `height` if width is not defined.", + "description": "Height of a texture that text will be rendered on. If not provided, the resulting texture will be sized based on the defined text but limited to `max_height` value.\n\nIt's an error to provide `height` if `width` is not defined.", "type": [ "number", "null" @@ -369,7 +382,7 @@ "format": "float" }, "max_width": { - "description": "(default=7682) Maximal width. Limits the width of a texture that text will be rendered on. Value is ignored if width is defined.", + "description": "(default=`7682`) Maximal `width`. Limits the width of the texture that the text will be rendered on. Value is ignored if `width` is defined.", "type": [ "number", "null" @@ -377,7 +390,7 @@ "format": "float" }, "max_height": { - "description": "(default=4320) Maximal height. Limits the height of a texture that text will be rendered on. Value is ignored if height is defined.", + "description": "(default=`4320`) Maximal height. Limits the height of the texture that the text will be rendered on. Value is ignored if height is defined.", "type": [ "number", "null" @@ -398,7 +411,7 @@ "format": "float" }, "color_rgba": { - "description": "(default=\"#FFFFFFFF\") Font color in `#RRGGBBAA` format.", + "description": "(default=`\"#FFFFFFFF\"`) Font color in `#RRGGBBAA` format.", "anyOf": [ { "$ref": "#/definitions/RGBAColor" @@ -409,7 +422,7 @@ ] }, "background_color_rgba": { - "description": "(default=\"#00000000\") Background color in `#RRGGBBAA` format.", + "description": "(default=`\"#00000000\"`) Background color in `#RRGGBBAA` format.", "anyOf": [ { "$ref": "#/definitions/RGBAColor" @@ -420,14 +433,14 @@ ] }, "font_family": { - "description": "(default=\"Verdana\") Font family.\n\nProvide family-name for specific font. \"generic-family\" values like e.g. \"sans-serif\" will not work. https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#family-name-value", + "description": "(default=`\"Verdana\"`) Font family. Provide [family-name](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#family-name-value) for a specific font. \"generic-family\" values like e.g. \"sans-serif\" will not work.", "type": [ "string", "null" ] }, "style": { - "description": "(default=\"normal\") Font style. The selected font needs to support this specific style.", + "description": "(default=`\"normal\"`) Font style. The selected font needs to support the specified style.", "anyOf": [ { "$ref": "#/definitions/TextStyle" @@ -438,7 +451,7 @@ ] }, "align": { - "description": "(default=\"left\") Text align.", + "description": "(default=`\"left\"`) Text align.", "anyOf": [ { "$ref": "#/definitions/HorizontalAlign" @@ -449,7 +462,7 @@ ] }, "wrap": { - "description": "(default=\"none\") Text wrapping options.", + "description": "(default=`\"none\"`) Text wrapping options.", "anyOf": [ { "$ref": "#/definitions/TextWrapMode" @@ -460,7 +473,7 @@ ] }, "weight": { - "description": "(default=\"normal\") Font weight. The selected font needs to support this specific weight.", + "description": "(default=`\"normal\"`) Font weight. The selected font needs to support the specified weight.", "anyOf": [ { "$ref": "#/definitions/TextWeight" @@ -486,6 +499,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -496,6 +510,7 @@ ] }, "children": { + "description": "List of component's children.", "type": [ "array", "null" @@ -521,7 +536,7 @@ "format": "float" }, "background_color_rgba": { - "description": "(default=\"#00000000\") Background color in a \"#RRGGBBAA\" format.", + "description": "(default=`\"#00000000\"`) Background color in a `\"#RRGGBBAA\"` format.", "anyOf": [ { "$ref": "#/definitions/RGBAColor" @@ -532,7 +547,7 @@ ] }, "tile_aspect_ratio": { - "description": "(default=\"16:9\") Aspect ration of a tile in \"W:H\" format, where W and H are integers.", + "description": "(default=`\"16:9\"`) Aspect ratio of a tile in `\"W:H\"` format, where W and H are integers.", "anyOf": [ { "$ref": "#/definitions/AspectRatio" @@ -543,7 +558,7 @@ ] }, "margin": { - "description": "(default=0) Margin of each tile in pixels.", + "description": "(default=`0`) Margin of each tile in pixels.", "type": [ "number", "null" @@ -551,15 +566,15 @@ "format": "float" }, "padding": { - "description": "(default=0) Padding on each tile in pixels.", + "description": "(default=`0`) Padding on each tile in pixels.", "type": [ "number", "null" ], "format": "float" }, - "horizontal_alignment": { - "description": "(default=\"center\") Horizontal alignment of tiles.", + "horizontal_align": { + "description": "(default=`\"center\"`) Horizontal alignment of tiles.", "anyOf": [ { "$ref": "#/definitions/HorizontalAlign" @@ -569,8 +584,8 @@ } ] }, - "vertical_alignment": { - "description": "(default=\"center\") Vertical alignment of tiles.", + "vertical_align": { + "description": "(default=`\"center\"`) Vertical alignment of tiles.", "anyOf": [ { "$ref": "#/definitions/VerticalAlign" @@ -597,6 +612,7 @@ ] }, "id": { + "description": "Id of a component.", "anyOf": [ { "$ref": "#/definitions/ComponentId" @@ -607,12 +623,18 @@ ] }, "child": { - "$ref": "#/definitions/Component" + "description": "List of component's children.", + "allOf": [ + { + "$ref": "#/definitions/Component" + } + ] }, "mode": { + "description": "Resize mode:\n\n- `\"fit\"` - Resize the component proportionally, so one of the dimensions is the same as its parent, but it still fits inside it.\n\n- `\"fill\"` - Resize the component proportionally, so one of the dimensions is the same as its parent and the entire area of the parent is covered. Parts of a child that do not fit inside the parent are not rendered.", "anyOf": [ { - "$ref": "#/definitions/ResizeMode" + "$ref": "#/definitions/RescaleMode" }, { "type": "null" @@ -620,6 +642,7 @@ ] }, "horizontal_align": { + "description": "(default=`\"center\"`) Horizontal alignment.", "anyOf": [ { "$ref": "#/definitions/HorizontalAlign" @@ -630,6 +653,7 @@ ] }, "vertical_align": { + "description": "(default=`\"center\"`) Vertical alignment.", "anyOf": [ { "$ref": "#/definitions/VerticalAlign" @@ -656,7 +680,7 @@ "format": "float" }, "top": { - "description": "Distance between the top edge of this component and the top edge of its parent. If this field is defined, then component will ignore a layout defined by its parent.", + "description": "Distance in pixels between this component's top edge and its parent's top edge. If this field is defined, then the component will ignore a layout defined by its parent.", "type": [ "number", "null" @@ -664,7 +688,7 @@ "format": "float" }, "left": { - "description": "Distance between the left edge of this component and the left edge of its parent. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Distance in pixels between this component's left edge and its parent's left edge. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -672,7 +696,7 @@ "format": "float" }, "bottom": { - "description": "Distance between the bottom edge of this component and the bottom edge of its parent. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Distance in pixels between this component's bottom edge and its parent's bottom edge. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -680,7 +704,7 @@ "format": "float" }, "right": { - "description": "Distance between the right edge of this component and the right edge of its parent. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Distance in pixels between this component's right edge and its parent's right edge. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -688,7 +712,7 @@ "format": "float" }, "rotation": { - "description": "Rotation of a component in degrees. If this field is defined, this element will be absolutely positioned, instead of being laid out by it's parent.", + "description": "Rotation of a component in degrees. If this field is defined, this element will be absolutely positioned, instead of being laid out by its parent.", "type": [ "number", "null" @@ -696,7 +720,7 @@ "format": "float" }, "transition": { - "description": "Defines how this component will behave during a scene update. This will only have an effect if previous scene already contained a View component with the same id.", + "description": "Defines how this component will behave during a scene update. This will only have an effect if the previous scene already contained a View component with the same id.", "anyOf": [ { "$ref": "#/definitions/Transition" @@ -731,6 +755,7 @@ ], "properties": { "duration_ms": { + "description": "Duration of a transition in milliseconds.", "type": "number", "format": "double" } @@ -739,21 +764,21 @@ "Overflow": { "oneOf": [ { - "description": "Components that are outside of their parent area will be rendered.", + "description": "Render everything, including content that extends beyond their parent.", "type": "string", "enum": [ "visible" ] }, { - "description": "Only render parts of the children that are inside their parent area.", + "description": "Render only parts of the children that are inside their parent area.", "type": "string", "enum": [ "hidden" ] }, { - "description": "If children component are to big to fit inside the parent resize everything inside to fit.\n\nComponents that have dynamic size will be treated as if they had a size 0 when calculating scaling factor.\n\nWarning: This will resize everything inside even absolutely positioned elements. For example, if you have an element in the bottom right corner and content will be rescaled by a factor 0.5x then that component will end up in the middle of it's parent", + "description": "If children components are too big to fit inside the parent, resize everything inside to fit.\n\nComponents that have unknown sizes will be treated as if they had a size 0 when calculating scaling factor.\n\n:::warning\n\nThis will resize everything inside, even absolutely positioned elements. For example, if you have an element in the bottom right corner and the content will be rescaled by a factor 0.5x, then that component will end up in the middle of its parent\n\n:::", "type": "string", "enum": [ "fit" @@ -1073,7 +1098,7 @@ ] }, "TextWeight": { - "description": "Font weight, based on [OpenType specification](https://learn.microsoft.com/en-gb/typography/opentype/spec/os2#usweightclass).", + "description": "Font weight, based on the [OpenType specification](https://learn.microsoft.com/en-gb/typography/opentype/spec/os2#usweightclass).", "oneOf": [ { "description": "Weight 100.", @@ -1152,7 +1177,7 @@ "justified" ] }, - "ResizeMode": { + "RescaleMode": { "type": "string", "enum": [ "fit", diff --git a/snapshot_tests/tiles/align_center_with_03_inputs.scene.json b/snapshot_tests/tiles/align_center_with_03_inputs.scene.json index 5fd788801..b53ba6acc 100644 --- a/snapshot_tests/tiles/align_center_with_03_inputs.scene.json +++ b/snapshot_tests/tiles/align_center_with_03_inputs.scene.json @@ -2,8 +2,8 @@ "output_id": "output_1", "root": { "type": "tiles", - "vertical_alignment": "center", - "horizontal_alignment": "center", + "vertical_align": "center", + "horizontal_align": "center", "children": [ { "type": "input_stream", diff --git a/snapshot_tests/tiles/align_top_left_with_03_inputs.scene.json b/snapshot_tests/tiles/align_top_left_with_03_inputs.scene.json index 27e8d634a..11bf36157 100644 --- a/snapshot_tests/tiles/align_top_left_with_03_inputs.scene.json +++ b/snapshot_tests/tiles/align_top_left_with_03_inputs.scene.json @@ -2,8 +2,8 @@ "output_id": "output_1", "root": { "type": "tiles", - "vertical_alignment": "top", - "horizontal_alignment": "left", + "vertical_align": "top", + "horizontal_align": "left", "children": [ { "type": "input_stream", diff --git a/snapshot_tests/tiles/align_with_margin_and_padding_with_03_inputs.scene.json b/snapshot_tests/tiles/align_with_margin_and_padding_with_03_inputs.scene.json index 469cf92ba..825574c59 100644 --- a/snapshot_tests/tiles/align_with_margin_and_padding_with_03_inputs.scene.json +++ b/snapshot_tests/tiles/align_with_margin_and_padding_with_03_inputs.scene.json @@ -2,8 +2,8 @@ "output_id": "output_1", "root": { "type": "tiles", - "vertical_alignment": "top", - "horizontal_alignment": "left", + "vertical_align": "top", + "horizontal_align": "left", "margin": 20, "padding": 20, "children": [ diff --git a/src/bin/generate_docs/main.rs b/src/bin/generate_docs/main.rs index d26c281ec..07f400407 100644 --- a/src/bin/generate_docs/main.rs +++ b/src/bin/generate_docs/main.rs @@ -45,16 +45,9 @@ fn main() { ) .unwrap(); } - - // TODO: Make it work the same way `renderers` work - let tmp_components_path = - PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("docs/pages/api/components"); - if !tmp_components_path.exists() { - fs::create_dir(&tmp_components_path).unwrap(); - } for page in component_pages { fs::write( - tmp_components_path.join(format!("{}.md", page.title)), + docs_path.join(format!("component-{}.md", page.title)), page.to_markdown(), ) .unwrap(); diff --git a/src/types/component.rs b/src/types/component.rs index 116f9feec..42e7f9f09 100644 --- a/src/types/component.rs +++ b/src/types/component.rs @@ -19,19 +19,21 @@ pub enum Component { Rescaler(Rescaler), } -/// Component representing incoming RTP stream. Specific streams can be identified -/// by an `input_id` that was part of a `RegisterInputStream` request. #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct InputStream { + /// Id of a component. pub id: Option, + /// Id of an input. It identifies a stream registered using a [`RegisterInputStream`](../routes#register-input-stream) request. pub input_id: InputId, } #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct View { + /// Id of a component. pub id: Option, + /// List of component's children. pub children: Option>, /// Width of a component in pixels. Required when using absolute positioning. @@ -39,56 +41,62 @@ pub struct View { /// Height of a component in pixels. Required when using absolute positioning. pub height: Option, - /// Direction defines how static children are positioned inside the View component. - /// "row" - Children positioned from left to right. - /// "column" - Children positioned from top to bottom. + /// Direction defines how static children are positioned inside a View component. + /// + /// - `"row"` - Children positioned from left to right. + /// + /// - `"column"` - Children positioned from top to bottom. pub direction: Option, - /// Distance between the top edge of this component and the top edge of its parent. - /// If this field is defined, then component will ignore a layout defined by its parent. + /// Distance in pixels between this component's top edge and its parent's top edge. + /// If this field is defined, then the component will ignore a layout defined by its parent. pub top: Option, - /// Distance between the left edge of this component and the left edge of its parent. + /// Distance in pixels between this component's left edge and its parent's left edge. /// If this field is defined, this element will be absolutely positioned, instead of being - /// laid out by it's parent. + /// laid out by its parent. pub left: Option, - /// Distance between the bottom edge of this component and the bottom edge of its parent. + /// Distance in pixels between the bottom edge of this component and the bottom edge of its parent. /// If this field is defined, this element will be absolutely positioned, instead of being - /// laid out by it's parent. + /// laid out by its parent. pub bottom: Option, - /// Distance between the right edge of this component and the right edge of its parent. + /// Distance in pixels between this component's right edge and its parent's right edge. /// If this field is defined, this element will be absolutely positioned, instead of being - /// laid out by it's parent. + /// laid out by its parent. pub right: Option, /// Rotation of a component in degrees. If this field is defined, this element will be - /// absolutely positioned, instead of being laid out by it's parent. + /// absolutely positioned, instead of being laid out by its parent. pub rotation: Option, /// Defines how this component will behave during a scene update. This will only have an - /// effect if previous scene already contained a View component with the same id. + /// effect if the previous scene already contained a View component with the same id. pub transition: Option, - /// (default="hidden") Controls what happens to content that is too big to fit into an area. + /// (default=`"hidden"`) Controls what happens to content that is too big to fit into an area. pub overflow: Option, - /// (default="#00000000") Background color in a "#RRGGBBAA" format. + /// (default=`"#00000000"`) Background color in a `"#RRGGBBAA"` format. pub background_color_rgba: Option, } #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum Overflow { - /// Components that are outside of their parent area will be rendered. + /// Render everything, including content that extends beyond their parent. Visible, - /// Only render parts of the children that are inside their parent area. + /// Render only parts of the children that are inside their parent area. Hidden, - /// If children component are to big to fit inside the parent resize everything inside to fit. + /// If children components are too big to fit inside the parent, resize everything inside to fit. /// - /// Components that have dynamic size will be treated as if they had a size 0 when calculating + /// Components that have unknown sizes will be treated as if they had a size 0 when calculating /// scaling factor. /// - /// Warning: This will resize everything inside even absolutely positioned - /// elements. For example, if you have an element in the bottom right corner and content will - /// be rescaled by a factor 0.5x then that component will end up in the middle of it's parent + /// :::warning + /// + /// This will resize everything inside, even absolutely positioned elements. For example, if + /// you have an element in the bottom right corner and the content will be rescaled by a factor 0.5x, + /// then that component will end up in the middle of its parent + /// + /// ::: Fit, } @@ -102,12 +110,22 @@ pub enum ViewDirection { #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct Rescaler { - // TODO: better name + /// Id of a component. pub id: Option, + /// List of component's children. pub child: Box, - pub mode: Option, + /// Resize mode: + /// + /// - `"fit"` - Resize the component proportionally, so one of the dimensions is the same as its parent, + /// but it still fits inside it. + /// + /// - `"fill"` - Resize the component proportionally, so one of the dimensions is the same as its + /// parent and the entire area of the parent is covered. Parts of a child that do not fit inside the parent are not rendered. + pub mode: Option, + /// (default=`"center"`) Horizontal alignment. pub horizontal_align: Option, + /// (default=`"center"`) Vertical alignment. pub vertical_align: Option, /// Width of a component in pixels. Required when using absolute positioning. @@ -115,33 +133,33 @@ pub struct Rescaler { /// Height of a component in pixels. Required when using absolute positioning. pub height: Option, - /// Distance between the top edge of this component and the top edge of its parent. - /// If this field is defined, then component will ignore a layout defined by its parent. + /// Distance in pixels between this component's top edge and its parent's top edge. + /// If this field is defined, then the component will ignore a layout defined by its parent. pub top: Option, - /// Distance between the left edge of this component and the left edge of its parent. + /// Distance in pixels between this component's left edge and its parent's left edge. /// If this field is defined, this element will be absolutely positioned, instead of being - /// laid out by it's parent. + /// laid out by its parent. pub left: Option, - /// Distance between the bottom edge of this component and the bottom edge of its parent. + /// Distance in pixels between this component's bottom edge and its parent's bottom edge. /// If this field is defined, this element will be absolutely positioned, instead of being - /// laid out by it's parent. + /// laid out by its parent. pub bottom: Option, - /// Distance between the right edge of this component and the right edge of its parent. + /// Distance in pixels between this component's right edge and its parent's right edge. /// If this field is defined, this element will be absolutely positioned, instead of being - /// laid out by it's parent. + /// laid out by its parent. pub right: Option, /// Rotation of a component in degrees. If this field is defined, this element will be - /// absolutely positioned, instead of being laid out by it's parent. + /// absolutely positioned, instead of being laid out by its parent. pub rotation: Option, /// Defines how this component will behave during a scene update. This will only have an - /// effect if previous scene already contained a View component with the same id. + /// effect if the previous scene already contained a View component with the same id. pub transition: Option, } #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(rename_all = "snake_case")] -pub enum ResizeMode { +pub enum RescaleMode { Fit, Fill, } @@ -150,16 +168,18 @@ pub enum ResizeMode { #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct WebView { + /// Id of a component. pub id: Option, + /// List of component's children. pub children: Option>, - /// ID of a previously registered `WebRenderer`. + /// Id of a web renderer instance. It identifies an instance registered using a [`RegisterRenderer`](../routes#register-renderer) request. /// ///

/// /// :::warning /// - /// You can only refer to specific instance in one Component at the time. + /// You can only refer to specific instances in one Component at a time. /// /// ::: pub instance_id: RendererId, @@ -168,19 +188,22 @@ pub struct WebView { #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct Image { + /// Id of a component. pub id: Option, - /// ID of a previously registered Image. + /// Id of an image. It identifies an image registered using a [`RegisterRenderer`](../routes#register-renderer) request. pub image_id: RendererId, } #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct Shader { + /// Id of a component. pub id: Option, + /// List of component's children. pub children: Option>, - /// ID of a previously registered Shader. + /// Id of a shader. It identifies a shader registered using a [`RegisterRenderer`](../routes#register-renderer) request. pub shader_id: RendererId, /// Object that will be serialized into a `struct` and passed inside the shader as: /// @@ -192,7 +215,11 @@ pub struct Shader { /// /// ``` /// - /// Note: This object's structure must match the structure defined in a shader source code. + /// :::note + /// + /// This object's structure must match the structure defined in a shader source code. + /// + /// ::: pub shader_param: Option, /// Resolution of a texture where shader will be executed. pub resolution: Resolution, @@ -223,21 +250,22 @@ pub struct ShaderParamStructField { #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct Text { + /// Id of a component. pub id: Option, pub text: Arc, - /// Width of a texture that text will be rendered on. If not provided the resulting texture - /// will be sized based on the defined text, but limited to `max_width` value. + /// Width of a texture that text will be rendered on. If not provided, the resulting texture + /// will be sized based on the defined text but limited to `max_width` value. pub width: Option, - /// Height of a texture that text will be rendered on. If not provided the resulting texture - /// will be sized based on the defined text, but limited to `max_width` value. + /// Height of a texture that text will be rendered on. If not provided, the resulting texture + /// will be sized based on the defined text but limited to `max_height` value. /// - /// It's an error to provide `height` if width is not defined. + /// It's an error to provide `height` if `width` is not defined. pub height: Option, - /// (default=7682) Maximal width. Limits the width of a texture that text will be rendered on. - /// Value is ignored if width is defined. + /// (default=`7682`) Maximal `width`. Limits the width of the texture that the text will be rendered on. + /// Value is ignored if `width` is defined. pub max_width: Option, - /// (default=4320) Maximal height. Limits the height of a texture that text will be rendered on. + /// (default=`4320`) Maximal height. Limits the height of the texture that the text will be rendered on. /// Value is ignored if height is defined. pub max_height: Option, @@ -245,22 +273,20 @@ pub struct Text { pub font_size: f32, /// Distance between lines in pixels. Defaults to the value of the `font_size` property. pub line_height: Option, - /// (default="#FFFFFFFF") Font color in `#RRGGBBAA` format. + /// (default=`"#FFFFFFFF"`) Font color in `#RRGGBBAA` format. pub color_rgba: Option, - /// (default="#00000000") Background color in `#RRGGBBAA` format. + /// (default=`"#00000000"`) Background color in `#RRGGBBAA` format. pub background_color_rgba: Option, - /// (default="Verdana") Font family. - /// - /// Provide family-name for specific font. "generic-family" values like e.g. "sans-serif" will not work. - /// https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#family-name-value + /// (default=`"Verdana"`) Font family. Provide [family-name](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#family-name-value) + /// for a specific font. "generic-family" values like e.g. "sans-serif" will not work. pub font_family: Option>, - /// (default="normal") Font style. The selected font needs to support this specific style. + /// (default=`"normal"`) Font style. The selected font needs to support the specified style. pub style: Option, - /// (default="left") Text align. + /// (default=`"left"`) Text align. pub align: Option, - /// (default="none") Text wrapping options. + /// (default=`"none"`) Text wrapping options. pub wrap: Option, - /// (default="normal") Font weight. The selected font needs to support this specific weight. + /// (default=`"normal"`) Font weight. The selected font needs to support the specified weight. pub weight: Option, } @@ -283,7 +309,7 @@ pub enum TextWrapMode { Word, } -/// Font weight, based on [OpenType specification](https://learn.microsoft.com/en-gb/typography/opentype/spec/os2#usweightclass). +/// Font weight, based on the [OpenType specification](https://learn.microsoft.com/en-gb/typography/opentype/spec/os2#usweightclass). #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum TextWeight { @@ -317,7 +343,9 @@ pub enum Interpolation { #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] #[serde(deny_unknown_fields)] pub struct Tiles { + /// Id of a component. pub id: Option, + /// List of component's children. pub children: Option>, /// Width of a component in pixels. @@ -325,16 +353,16 @@ pub struct Tiles { /// Height of a component in pixels. pub height: Option, - /// (default="#00000000") Background color in a "#RRGGBBAA" format. + /// (default=`"#00000000"`) Background color in a `"#RRGGBBAA"` format. pub background_color_rgba: Option, - /// (default="16:9") Aspect ration of a tile in "W:H" format, where W and H are integers. + /// (default=`"16:9"`) Aspect ratio of a tile in `"W:H"` format, where W and H are integers. pub tile_aspect_ratio: Option, - /// (default=0) Margin of each tile in pixels. + /// (default=`0`) Margin of each tile in pixels. pub margin: Option, - /// (default=0) Padding on each tile in pixels. + /// (default=`0`) Padding on each tile in pixels. pub padding: Option, - /// (default="center") Horizontal alignment of tiles. - pub horizontal_alignment: Option, - /// (default="center") Vertical alignment of tiles. - pub vertical_alignment: Option, + /// (default=`"center"`) Horizontal alignment of tiles. + pub horizontal_align: Option, + /// (default=`"center"`) Vertical alignment of tiles. + pub vertical_align: Option, } diff --git a/src/types/from_component.rs b/src/types/from_component.rs index c2279a465..081578465 100644 --- a/src/types/from_component.rs +++ b/src/types/from_component.rs @@ -165,9 +165,9 @@ impl TryFrom for scene::RescalerComponent { } }; let mode = match rescaler.mode { - Some(ResizeMode::Fit) => scene::ResizeMode::Fit, - Some(ResizeMode::Fill) => scene::ResizeMode::Fill, - None => scene::ResizeMode::Fit, + Some(RescaleMode::Fit) => scene::RescaleMode::Fit, + Some(RescaleMode::Fill) => scene::RescaleMode::Fill, + None => scene::RescaleMode::Fit, }; Ok(Self { id: rescaler.id.map(Into::into), @@ -347,14 +347,11 @@ impl TryFrom for scene::TilesComponent { .unwrap_or(Ok((16, 9)))?, margin: tiles.margin.unwrap_or(0.0), padding: tiles.padding.unwrap_or(0.0), - horizontal_alignment: tiles - .horizontal_alignment + horizontal_align: tiles + .horizontal_align .unwrap_or(HorizontalAlign::Center) .into(), - vertical_alignment: tiles - .vertical_alignment - .unwrap_or(VerticalAlign::Center) - .into(), + vertical_align: tiles.vertical_align.unwrap_or(VerticalAlign::Center).into(), }; Ok(result) } diff --git a/src/types/from_renderer.rs b/src/types/from_renderer.rs index b5d68e372..0894983fc 100644 --- a/src/types/from_renderer.rs +++ b/src/types/from_renderer.rs @@ -24,10 +24,7 @@ impl TryFrom for renderer_spec::RendererSpec { let spec = renderer_spec::ShaderSpec { shader_id: spec.shader_id.into(), source: spec.source, - fallback_strategy: spec - .fallback_strategy - .map(Into::into) - .unwrap_or(renderer_spec::FallbackStrategy::FallbackIfAllInputsMissing), + fallback_strategy: renderer_spec::FallbackStrategy::FallbackIfAllInputsMissing, }; Ok(Self::Shader(spec)) } @@ -54,10 +51,7 @@ impl TryFrom for renderer_spec::RendererSpec { instance_id: spec.instance_id.into(), url: spec.url, resolution: spec.resolution.into(), - fallback_strategy: spec - .fallback_strategy - .map(Into::into) - .unwrap_or(renderer_spec::FallbackStrategy::FallbackIfAllInputsMissing), + fallback_strategy: renderer_spec::FallbackStrategy::FallbackIfAllInputsMissing, embedding_method, }; Ok(Self::WebRenderer(spec)) diff --git a/src/types/renderer.rs b/src/types/renderer.rs index f7ae053b2..251e44fb1 100644 --- a/src/types/renderer.rs +++ b/src/types/renderer.rs @@ -17,7 +17,6 @@ pub enum FallbackStrategy { pub struct ShaderSpec { pub shader_id: RendererId, pub source: String, - pub fallback_strategy: Option, } #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] @@ -27,7 +26,6 @@ pub struct WebRendererSpec { pub url: String, pub resolution: Resolution, pub embedding_method: Option, - pub fallback_strategy: Option, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] diff --git a/src/types/util.rs b/src/types/util.rs index 0eadf44f1..1bd770938 100644 --- a/src/types/util.rs +++ b/src/types/util.rs @@ -13,6 +13,7 @@ pub struct Resolution { #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] pub struct Transition { + /// Duration of a transition in milliseconds. pub duration_ms: f64, }