import { z } from "zod"; import { BaseEntity, EllipseEntity, EntityType, RectEntity, TextEntity, } from "./Entities"; import { AnimatedTransform, AnimatedVec2 } from "./Values"; import { TextPaint } from "./Paint"; import { AnimatedProperties } from "./AnimatedProperty"; export const AnimationData = z.object({ offset: z.number(), duration: z.number(), visible: z.boolean().optional().default(true), }); export const AnimatedStaggeredTextEntity = BaseEntity.extend({ /** Transform applied to the whole layer. */ transform: AnimatedTransform, /** The staggered delay that is applied for each letter. Gets multiplied by the index of the letter. */ stagger: z.number().min(0), /** These properties get applied to each letter */ letter: z.object({ transform: AnimatedTransform, paint: TextPaint, }), text: z.string(), origin: AnimatedVec2, animation_data: AnimationData, type: z.literal(EntityType.Enum.StaggeredText), }); export const AnimatedRectEntity = RectEntity.extend({ position: AnimatedVec2, size: AnimatedVec2, origin: AnimatedVec2, transform: AnimatedTransform.optional(), animation_data: AnimationData, }); export const AnimatedTextEntity = TextEntity.extend({ origin: AnimatedVec2, transform: AnimatedTransform.optional(), animation_data: AnimationData, }); export const AnimatedEllipseEntity = EllipseEntity.extend({ radius: AnimatedVec2, position: AnimatedVec2, origin: AnimatedVec2, transform: AnimatedTransform.optional(), animation_data: AnimationData, }); export const AnimatedEntity = z.discriminatedUnion("type", [ AnimatedRectEntity, AnimatedTextEntity, AnimatedStaggeredTextEntity, AnimatedEllipseEntity, ]); export const AnimatedEntities = z.array(AnimatedEntity); export function animatedTransformToAnimatedProperties( animatedTransform: z.input, basePath?: string ): z.input { return [ { animatedValue: animatedTransform.translate, label: "Translation", propertyPath: basePath ? basePath + ".transform.translate" : "transform.translate", }, { animatedValue: animatedTransform.rotate, label: "Rotation", propertyPath: basePath ? basePath + ".transform.rotate" : "transform.rotate", }, { animatedValue: animatedTransform.scale, label: "Scale", propertyPath: basePath ? basePath + ".transform.scale" : "transform.scale", }, { animatedValue: animatedTransform.skew, label: "Skew", propertyPath: basePath ? basePath + ".transform.skew" : "transform.skew", }, ]; } export function getAnimatedPropertiesByAnimatedEntity( animatedEntity: z.input ) { const animatedProperties: z.input = []; switch (animatedEntity.type) { case "Ellipse": animatedProperties.push({ propertyPath: "origin", animatedValue: animatedEntity.origin, label: "Origin", }); animatedProperties.push({ propertyPath: "radius", animatedValue: animatedEntity.radius, label: "Radius", }); if (animatedEntity.transform) { animatedProperties.push( ...animatedTransformToAnimatedProperties(animatedEntity.transform) ); } break; case "Rect": animatedProperties.push({ propertyPath: "origin", animatedValue: animatedEntity.origin, label: "Origin", }); animatedProperties.push({ propertyPath: "size", animatedValue: animatedEntity.size, label: "Size", }); if (animatedEntity.transform) { animatedProperties.push( ...animatedTransformToAnimatedProperties(animatedEntity.transform) ); } break; case "StaggeredText": animatedProperties.push({ propertyPath: "origin", animatedValue: animatedEntity.origin, label: "Origin", }); if (animatedEntity.transform) { animatedProperties.push( ...animatedTransformToAnimatedProperties(animatedEntity.transform) ); } if (animatedEntity.letter.transform) { animatedProperties.push( ...animatedTransformToAnimatedProperties( animatedEntity.letter.transform, "letter" ) ); } break; case "Text": animatedProperties.push({ propertyPath: "origin", animatedValue: animatedEntity.origin, label: "Origin", }); if (animatedEntity.transform) { animatedProperties.push( ...animatedTransformToAnimatedProperties(animatedEntity.transform) ); } break; } return animatedProperties; } export function getAnimatedPropertiesByAnimatedEnties( animatedEntities: z.input ) { const animatedProperties: z.input = []; animatedEntities.forEach((aEnt) => { animatedProperties.push(...getAnimatedPropertiesByAnimatedEntity(aEnt)); }); }