diff options
Diffstat (limited to 'apps/web/src/types')
| -rw-r--r-- | apps/web/src/types/animation.ts | 89 | ||||
| -rw-r--r-- | apps/web/src/types/drag.ts | 15 | ||||
| -rw-r--r-- | apps/web/src/types/effects.ts | 45 | ||||
| -rw-r--r-- | apps/web/src/types/glsl.d.ts | 4 | ||||
| -rw-r--r-- | apps/web/src/types/rendering.ts | 9 | ||||
| -rw-r--r-- | apps/web/src/types/timeline.ts | 69 |
6 files changed, 216 insertions, 15 deletions
diff --git a/apps/web/src/types/animation.ts b/apps/web/src/types/animation.ts new file mode 100644 index 00000000..b9ca91af --- /dev/null +++ b/apps/web/src/types/animation.ts @@ -0,0 +1,89 @@ +export const ANIMATION_PROPERTY_PATHS = [ + "transform.position.x", + "transform.position.y", + "transform.scale", + "transform.rotate", + "opacity", + "volume", +] as const; + +export type AnimationPropertyPath = (typeof ANIMATION_PROPERTY_PATHS)[number]; + +export type AnimationValueKind = "number" | "color" | "discrete"; +export type DiscreteValue = boolean | string; +export type AnimationValue = number | string | boolean; + +export type NumberKeyframeInterpolation = "linear" | "hold"; +export type ColorKeyframeInterpolation = "linear" | "hold"; +export type DiscreteKeyframeInterpolation = "hold"; +export type AnimationInterpolation = + | NumberKeyframeInterpolation + | ColorKeyframeInterpolation + | DiscreteKeyframeInterpolation; + +interface BaseAnimationKeyframe< + TValue extends AnimationValue, + TInterpolation extends AnimationInterpolation, +> { + id: string; + time: number; // relative to element start time + value: TValue; + interpolation: TInterpolation; +} + +export interface NumberKeyframe + extends BaseAnimationKeyframe<number, NumberKeyframeInterpolation> {} + +export interface ColorKeyframe + extends BaseAnimationKeyframe<string, ColorKeyframeInterpolation> {} + +export interface DiscreteKeyframe + extends BaseAnimationKeyframe<DiscreteValue, DiscreteKeyframeInterpolation> {} + +export type AnimationKeyframe = NumberKeyframe | ColorKeyframe | DiscreteKeyframe; + +interface BaseAnimationChannel< + TValueKind extends AnimationValueKind, + TKeyframe extends AnimationKeyframe, +> { + valueKind: TValueKind; + keyframes: TKeyframe[]; +} + +export interface NumberAnimationChannel + extends BaseAnimationChannel<"number", NumberKeyframe> {} + +export interface ColorAnimationChannel + extends BaseAnimationChannel<"color", ColorKeyframe> {} + +export interface DiscreteAnimationChannel + extends BaseAnimationChannel<"discrete", DiscreteKeyframe> {} + +export type AnimationChannel = + | NumberAnimationChannel + | ColorAnimationChannel + | DiscreteAnimationChannel; + +export type ElementAnimationChannelMap = Record< + string, + AnimationChannel | undefined +>; + +export interface ElementAnimations { + channels: ElementAnimationChannelMap; +} + +export interface ElementKeyframe { + propertyPath: AnimationPropertyPath; + id: string; + time: number; + value: AnimationValue; + interpolation: AnimationInterpolation; +} + +export interface SelectedKeyframeRef { + trackId: string; + elementId: string; + propertyPath: AnimationPropertyPath; + keyframeId: string; +} diff --git a/apps/web/src/types/drag.ts b/apps/web/src/types/drag.ts index 61aba9b5..4e10d767 100644 --- a/apps/web/src/types/drag.ts +++ b/apps/web/src/types/drag.ts @@ -1,3 +1,5 @@ +import type { VisualElement } from "./timeline"; + interface BaseDragData { id: string; name: string; @@ -6,6 +8,7 @@ interface BaseDragData { export interface MediaDragData extends BaseDragData { type: "media"; mediaType: "image" | "video" | "audio"; + targetElementTypes?: ("video" | "image")[]; } export interface TextDragData extends BaseDragData { @@ -18,4 +21,14 @@ export interface StickerDragData extends BaseDragData { stickerId: string; } -export type TimelineDragData = MediaDragData | TextDragData | StickerDragData; +export interface EffectDragData extends BaseDragData { + type: "effect"; + effectType: string; + targetElementTypes: VisualElement["type"][]; +} + +export type TimelineDragData = + | MediaDragData + | TextDragData + | StickerDragData + | EffectDragData; diff --git a/apps/web/src/types/effects.ts b/apps/web/src/types/effects.ts new file mode 100644 index 00000000..cc369450 --- /dev/null +++ b/apps/web/src/types/effects.ts @@ -0,0 +1,45 @@ +export interface Effect { + id: string; + type: string; + params: EffectParamValues; + enabled: boolean; +} + +export type EffectParamType = "number" | "boolean" | "select" | "color"; + +export type EffectParamValues = Record<string, number | string | boolean>; + +export interface EffectParamDefinition { + key: string; + label: string; + type: EffectParamType; + default: number | string | boolean; + min?: number; + max?: number; + step?: number; + options?: Array<{ value: string; label: string }>; +} + +export interface WebGLEffectPass { + fragmentShader: string; + uniforms(params: { + effectParams: EffectParamValues; + width: number; + height: number; + }): Record<string, number | number[]>; +} + +export interface WebGLEffectRenderer { + type: "webgl"; + passes: WebGLEffectPass[]; +} + +export type EffectRenderer = WebGLEffectRenderer; + +export interface EffectDefinition { + type: string; + name: string; + keywords: string[]; + params: EffectParamDefinition[]; + renderer: EffectRenderer; +} diff --git a/apps/web/src/types/glsl.d.ts b/apps/web/src/types/glsl.d.ts new file mode 100644 index 00000000..4e93dbe5 --- /dev/null +++ b/apps/web/src/types/glsl.d.ts @@ -0,0 +1,4 @@ +declare module "*.glsl" { + const value: string; + export default value; +} diff --git a/apps/web/src/types/rendering.ts b/apps/web/src/types/rendering.ts index f5e18502..8c9763df 100644 --- a/apps/web/src/types/rendering.ts +++ b/apps/web/src/types/rendering.ts @@ -1,3 +1,12 @@ +export interface Transform { + scale: number; + position: { + x: number; + y: number; + }; + rotate: number; +} + export type BlendMode = | "normal" | "darken" diff --git a/apps/web/src/types/timeline.ts b/apps/web/src/types/timeline.ts index da96c7de..0c138f56 100644 --- a/apps/web/src/types/timeline.ts +++ b/apps/web/src/types/timeline.ts @@ -1,4 +1,6 @@ -import type { BlendMode } from "./rendering"; +import type { ElementAnimations } from "./animation"; +import type { Effect, EffectParamValues } from "./effects"; +import type { BlendMode, Transform } from "./rendering"; export interface Bookmark { time: number; @@ -17,7 +19,7 @@ export interface TScene { updatedAt: Date; } -export type TrackType = "video" | "text" | "audio" | "sticker"; +export type TrackType = "video" | "text" | "audio" | "sticker" | "effect"; interface BaseTrack { id: string; @@ -50,17 +52,21 @@ export interface StickerTrack extends BaseTrack { hidden: boolean; } -export type TimelineTrack = VideoTrack | TextTrack | AudioTrack | StickerTrack; - -export interface Transform { - scale: number; - position: { - x: number; - y: number; - }; - rotate: number; +export interface EffectTrack extends BaseTrack { + type: "effect"; + elements: EffectElement[]; + hidden: boolean; } +export type TimelineTrack = + | VideoTrack + | TextTrack + | AudioTrack + | StickerTrack + | EffectTrack; + +export type { Transform } from "./rendering"; + interface BaseAudioElement extends BaseTimelineElement { type: "audio"; volume: number; @@ -87,6 +93,8 @@ interface BaseTimelineElement { startTime: number; trimStart: number; trimEnd: number; + sourceDuration?: number; + animations?: ElementAnimations; } export interface VideoElement extends BaseTimelineElement { @@ -97,6 +105,7 @@ export interface VideoElement extends BaseTimelineElement { transform: Transform; opacity: number; blendMode?: BlendMode; + effects?: Effect[]; } export interface ImageElement extends BaseTimelineElement { @@ -106,6 +115,7 @@ export interface ImageElement extends BaseTimelineElement { transform: Transform; opacity: number; blendMode?: BlendMode; + effects?: Effect[]; } export interface TextElement extends BaseTimelineElement { @@ -114,7 +124,14 @@ export interface TextElement extends BaseTimelineElement { fontSize: number; fontFamily: string; color: string; - backgroundColor: string; + background: { + color: string; + cornerRadius?: number; + paddingX?: number; + paddingY?: number; + offsetX?: number; + offsetY?: number; + }; textAlign: "left" | "center" | "right"; fontWeight: "normal" | "bold"; fontStyle: "normal" | "italic"; @@ -125,6 +142,7 @@ export interface TextElement extends BaseTimelineElement { transform: Transform; opacity: number; blendMode?: BlendMode; + effects?: Effect[]; } export interface StickerElement extends BaseTimelineElement { @@ -134,14 +152,33 @@ export interface StickerElement extends BaseTimelineElement { transform: Transform; opacity: number; blendMode?: BlendMode; + effects?: Effect[]; +} + +export interface EffectElement extends BaseTimelineElement { + type: "effect"; + effectType: string; + params: EffectParamValues; } +export type VisualElement = + | VideoElement + | ImageElement + | TextElement + | StickerElement; + +export type ElementUpdatePatch = + | { transform: Transform } + | { opacity: number } + | { volume: number }; + export type TimelineElement = | AudioElement | VideoElement | ImageElement | TextElement - | StickerElement; + | StickerElement + | EffectElement; export type ElementType = TimelineElement["type"]; @@ -154,12 +191,14 @@ export type CreateVideoElement = Omit<VideoElement, "id">; export type CreateImageElement = Omit<ImageElement, "id">; export type CreateTextElement = Omit<TextElement, "id">; export type CreateStickerElement = Omit<StickerElement, "id">; +export type CreateEffectElement = Omit<EffectElement, "id">; export type CreateTimelineElement = | CreateAudioElement | CreateVideoElement | CreateImageElement | CreateTextElement - | CreateStickerElement; + | CreateStickerElement + | CreateEffectElement; export interface ElementDragState { isDragging: boolean; @@ -178,6 +217,7 @@ export interface DropTarget { isNewTrack: boolean; insertPosition: "above" | "below" | null; xPosition: number; + targetElement: { elementId: string; trackId: string } | null; } export interface ComputeDropTargetParams { @@ -193,6 +233,7 @@ export interface ComputeDropTargetParams { verticalDragDirection?: "up" | "down" | null; startTimeOverride?: number; excludeElementId?: string; + targetElementTypes?: string[]; } export interface ClipboardItem { |
