Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@companion-module/base",
"version": "1.14.0",
"version": "1.99.0",
"type": "commonjs",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
26 changes: 24 additions & 2 deletions src/host-api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ import type { OSCSomeArguments } from '../common/osc.js'
import type { SomeCompanionConfigField } from '../module-api/config.js'
import type { LogLevel, InstanceStatus } from '../module-api/enums.js'
import type { CompanionOptionValues, CompanionInputFieldBase } from '../module-api/input.js'
import type { CompanionButtonPresetDefinition, CompanionTextPresetDefinition } from '../module-api/preset.js'
import type {
CompanionButtonPresetDefinition,
CompanionLayeredButtonPresetDefinition,
CompanionTextPresetDefinition,
} from '../module-api/preset.js'
import type { CompanionHTTPRequest, CompanionHTTPResponse } from '../module-api/http.js'
import type { SomeCompanionActionInputField } from '../module-api/action.js'
import type { CompanionVariableValue } from '../module-api/variable.js'
import type { RemoteInfo } from 'dgram'
import type { OptionsObject } from '../util.js'
import type { JsonValue } from '../common/json-value.js'
import type { SomeButtonGraphicsElement } from '../module-api/graphics.js'

export interface ModuleToHostEventsV0 extends ModuleToHostEventsV0SharedSocket {
/** The connection has a message for the Companion log */
Expand All @@ -31,6 +36,8 @@ export interface ModuleToHostEventsV0 extends ModuleToHostEventsV0SharedSocket {
setVariableDefinitions: (msg: SetVariableDefinitionsMessage) => never
/** The presets provided by the connection have changed */
setPresetDefinitions: (msg: SetPresetDefinitionsMessage) => never
/** The graphics composite elements provided have changed */
setCompositeElementDefinitions: (msg: SetCompositeElementDefinitionsMessage) => never
/** The connection has some new values for variables */
setVariableValues: (msg: SetVariableValuesMessage) => never
/** The connection has some new values for feedbacks it is running */
Expand Down Expand Up @@ -224,7 +231,22 @@ export interface SetVariableDefinitionsMessage {
}

export interface SetPresetDefinitionsMessage {
presets: Array<(CompanionButtonPresetDefinition | CompanionTextPresetDefinition) & { id: string }>
presets: Array<
(CompanionButtonPresetDefinition | CompanionLayeredButtonPresetDefinition | CompanionTextPresetDefinition) & {
id: string
}
>
}

export interface SetCompositeElementDefinitionsMessage {
compositeElements: Array<{
id: string
type: 'composite'
name: string
description: string | undefined
options: EncodeIsVisible<SomeCompanionFeedbackInputField>[] // TODO module-lib - versioned types?
elements: SomeButtonGraphicsElement[]
}>
}

export interface SetVariableValuesMessage {
Expand Down
23 changes: 23 additions & 0 deletions src/module-api/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {
ParseVariablesInStringMessage,
ParseVariablesInStringResponseMessage,
SendOscMessage,
SetCompositeElementDefinitionsMessage,
SetPresetDefinitionsMessage,
SetStatusMessage,
SetVariableDefinitionsMessage,
Expand Down Expand Up @@ -53,6 +54,7 @@ import {
SharedUdpSocketMessageCallback,
SharedUdpSocketOptions,
} from './shared-udp-socket.js'
import { CompanionGraphicsCompositeElementDefinition } from './graphics-composite.js'

export interface InstanceBaseOptions {
/**
Expand Down Expand Up @@ -436,6 +438,27 @@ export abstract class InstanceBase<TConfig, TSecrets = undefined> implements Ins
this.#ipcWrapper.sendWithNoCb('setPresetDefinitions', { presets: hostPresets })
}

/**
* Set the composite graphics elements for this instance
* @param compositeElements The composite element definitions
*/
setCompositeElementDefinitions(compositeElements: CompanionGraphicsCompositeElementDefinition[]): void {
const hostCompositeElements: SetCompositeElementDefinitionsMessage['compositeElements'] = []

for (const compositeElement of compositeElements) {
hostCompositeElements.push({
id: compositeElement.id,
name: compositeElement.name,
type: compositeElement.type,
description: compositeElement.description,
options: serializeIsVisibleFn(compositeElement.options),
elements: compositeElement.elements,
})
}

this.#ipcWrapper.sendWithNoCb('setCompositeElementDefinitions', { compositeElements: hostCompositeElements })
}

/**
* Set the variable definitions for this instance
* @param variables The variable definitions
Expand Down
13 changes: 13 additions & 0 deletions src/module-api/graphics-composite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { SomeCompanionFeedbackInputField } from './feedback.js'
import type { SomeButtonGraphicsElement } from './graphics.js'

export interface CompanionGraphicsCompositeElementDefinition {
id: string
type: 'composite'

name: string
description?: string
options: SomeCompanionFeedbackInputField[]

elements: SomeButtonGraphicsElement[]
}
146 changes: 146 additions & 0 deletions src/module-api/graphics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// TODO: deduplicate
export type ExpressionOrValue<T> = { value: T; isExpression: false } | { value: string; isExpression: true }

/**
* The type of a button graphics element as stored in places where it can be edited
*/
export type SomeButtonGraphicsElement =
| ButtonGraphicsGroupElement
| ButtonGraphicsCompositeElement
| ButtonGraphicsTextElement
| ButtonGraphicsImageElement
| ButtonGraphicsBoxElement
| ButtonGraphicsLineElement
| ButtonGraphicsCircleElement

export interface ButtonGraphicsElementBase {
id?: string
name?: string

enabled?: ExpressionOrValue<boolean>
/* 0-100 */
opacity?: ExpressionOrValue<number>
}

export interface ButtonGraphicsDrawBounds {
/* 0-100 */
x?: ExpressionOrValue<number>
/* 0-100 */
y?: ExpressionOrValue<number>
/* 0-100 */
width?: ExpressionOrValue<number>
/* 0-100 */
height?: ExpressionOrValue<number>
}

export interface ButtonGraphicsCanvasElement {
// previewColor: number

decoration?: ExpressionOrValue<ButtonGraphicsDecorationType> // replaces show_topbar
}

export enum ButtonGraphicsDecorationType {
FollowDefault = 'default',
TopBar = 'topbar',
// BottomBar = 'bottombar', // Future
Border = 'border',
None = 'none',
}

export interface ButtonGraphicsGroupElement extends ButtonGraphicsElementBase, ButtonGraphicsDrawBounds {
type: 'group'

rotation?: ExpressionOrValue<number> // degrees 0-359

children: SomeButtonGraphicsElement[]
}

export interface ButtonGraphicsCompositeElement<TOptions = Record<string, any>>
extends ButtonGraphicsElementBase, ButtonGraphicsDrawBounds {
type: 'composite'

elementId: string

/**
* Custom elements have options defined by their composite definition
*/
options: { [key in keyof TOptions]?: ExpressionOrValue<TOptions[key]> }
}

export type HorizontalAlignment = 'left' | 'center' | 'right'
export type VerticalAlignment = 'top' | 'center' | 'bottom'

export type LineOrientation = 'inside' | 'center' | 'outside'

export type ImageFillMode = 'crop' | 'fill' | 'fit' | 'fit_or_shrink'

export interface ButtonGraphicsTextElement extends ButtonGraphicsElementBase, ButtonGraphicsDrawBounds {
type: 'text'

rotation?: ExpressionOrValue<number> // degrees 0-359

text: ExpressionOrValue<string>

fontsize?: ExpressionOrValue<'auto' | number> // TODO - other values?

color?: ExpressionOrValue<number>

halign?: ExpressionOrValue<HorizontalAlignment>
valign?: ExpressionOrValue<VerticalAlignment>

outlineColor?: ExpressionOrValue<number>
}

export interface ButtonGraphicsImageElement extends ButtonGraphicsElementBase, ButtonGraphicsDrawBounds {
type: 'image'

rotation?: ExpressionOrValue<number> // degrees 0-359

base64Image: ExpressionOrValue<string | null>

halign?: ExpressionOrValue<HorizontalAlignment>
valign?: ExpressionOrValue<VerticalAlignment>

fillMode?: ExpressionOrValue<ImageFillMode>
}

export interface ButtonGraphicsBorderProperties {
borderWidth?: ExpressionOrValue<number> // 0 to disable
borderColor?: ExpressionOrValue<number>
borderPosition?: ExpressionOrValue<LineOrientation>
}

export interface ButtonGraphicsBoxElement
extends ButtonGraphicsElementBase, ButtonGraphicsDrawBounds, ButtonGraphicsBorderProperties {
type: 'box'

rotation?: ExpressionOrValue<number> // degrees 0-359

color?: ExpressionOrValue<number>
}

export interface ButtonGraphicsLineElement extends ButtonGraphicsElementBase, ButtonGraphicsBorderProperties {
type: 'line'

/* 0-100 */
fromX?: ExpressionOrValue<number>
/* 0-100 */
fromY?: ExpressionOrValue<number>
/* 0-100 */
toX?: ExpressionOrValue<number>
/* 0-100 */
toY?: ExpressionOrValue<number>
}

export interface ButtonGraphicsCircleElement
extends ButtonGraphicsElementBase, ButtonGraphicsDrawBounds, ButtonGraphicsBorderProperties {
type: 'circle'

color?: ExpressionOrValue<number>

startAngle?: ExpressionOrValue<number> // degrees 0-359
endAngle?: ExpressionOrValue<number> // degrees 0-359

drawSlice?: ExpressionOrValue<boolean>
borderOnlyArc?: ExpressionOrValue<boolean>
}
2 changes: 2 additions & 0 deletions src/module-api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export * from './config.js'
export * from './enums.js'
export * from './feedback.js'
export * from './http.js'
export * from './graphics.js'
export * from './graphics-composite.js'
export * from './input.js'
export * from './preset.js'
export {
Expand Down
62 changes: 61 additions & 1 deletion src/module-api/preset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { CompanionFeedbackButtonStyleResult } from './feedback.js'
import type { ButtonGraphicsCanvasElement, ExpressionOrValue, SomeButtonGraphicsElement } from './graphics.js'
import type { CompanionOptionValues } from './input.js'
import type { CompanionButtonStyleProps } from './style.js'

Expand Down Expand Up @@ -37,6 +38,38 @@ export interface CompanionPresetFeedback {
headline?: string
}

/**
* The configuration of an feedback in a preset
*/
export interface CompanionPresetLayeredFeedback {
/** The id of the feedback definition */
feedbackId: string
/** The option values for the action */
options: CompanionOptionValues

/**
* Element styles to override when this feedback is active
*/
styleOverrides: CompanionPresetFeedbackStyleOverride[]

/**
* If a boolean feedback, invert the value of the feedback
*/
isInverted?: boolean
/**
* User editable description/comment for the feedback.
* Intended to descibe the purpose/intent of the feedback.
*/
headline?: string
}

export interface CompanionPresetFeedbackStyleOverride {
elementId: string
elementProperty: string
// Note: When overriding advanced feedbacks, this should be set to `{ isExpression: false, value: 'color' }` or similar to indicate which property it is using
override: ExpressionOrValue<any>
}

/**
* The configuration of an action in a preset
*/
Expand Down Expand Up @@ -77,6 +110,29 @@ export interface CompanionButtonPresetDefinition {
steps: CompanionButtonStepActions[]
}

/**
* The definition of a press button preset
*/
export interface CompanionLayeredButtonPresetDefinition {
/** The type of this preset */
type: 'layered-button'
/** The category of this preset, for grouping */
category: string
/** The name of this preset */
name: string

/** The drawing elements for this preset, this will be copied to the button */
elements: SomeButtonGraphicsElement[]

canvas?: ButtonGraphicsCanvasElement

/** Options for this preset */
options?: CompanionButtonPresetOptions
/** The feedbacks on the button */
feedbacks: CompanionPresetLayeredFeedback[]
steps: CompanionButtonStepActions[]
}

/**
* The definition of a text preset
*/
Expand Down Expand Up @@ -117,5 +173,9 @@ export interface CompanionButtonStepActions {
* The definitions of a group of feedbacks
*/
export interface CompanionPresetDefinitions {
[id: string]: CompanionButtonPresetDefinition | CompanionTextPresetDefinition | undefined
[id: string]:
| CompanionButtonPresetDefinition
| CompanionLayeredButtonPresetDefinition
| CompanionTextPresetDefinition
| undefined
}