improve ui
add track properties editor
This commit is contained in:
@@ -6,8 +6,9 @@ import {
|
||||
RectEntity,
|
||||
TextEntity,
|
||||
} from "./Entities";
|
||||
import { AnimatedVec2, AnimatedVec3 } from "./Values";
|
||||
import { AnimatedTransform, AnimatedVec2 } from "./Values";
|
||||
import { TextPaint } from "./Paint";
|
||||
import { AnimatedProperties } from "./AnimatedProperty";
|
||||
|
||||
export const AnimationData = z.object({
|
||||
offset: z.number(),
|
||||
@@ -15,17 +16,6 @@ export const AnimationData = z.object({
|
||||
visible: z.boolean().optional().default(true),
|
||||
});
|
||||
|
||||
export const AnimatedTransform = z.object({
|
||||
/** Translates by the given animated vec2 */
|
||||
translate: AnimatedVec2,
|
||||
/** Skews by the given animated vec2 */
|
||||
skew: AnimatedVec2,
|
||||
/** Rotates by the given animated vec2 */
|
||||
rotate: AnimatedVec3,
|
||||
/** Scales on the x and y axis by the given animated vec2 */
|
||||
scale: AnimatedVec2,
|
||||
});
|
||||
|
||||
export const AnimatedStaggeredTextEntity = BaseEntity.extend({
|
||||
/** Transform applied to the whole layer. */
|
||||
transform: AnimatedTransform,
|
||||
@@ -72,3 +62,133 @@ export const AnimatedEntity = z.discriminatedUnion("type", [
|
||||
]);
|
||||
|
||||
export const AnimatedEntities = z.array(AnimatedEntity);
|
||||
|
||||
export function animatedTransformToAnimatedProperties(
|
||||
animatedTransform: z.input<typeof AnimatedTransform>,
|
||||
basePath?: string
|
||||
): z.input<typeof AnimatedProperties> {
|
||||
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<typeof AnimatedEntity>
|
||||
) {
|
||||
const animatedProperties: z.input<typeof AnimatedProperties> = [];
|
||||
|
||||
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: "radius",
|
||||
animatedValue: animatedEntity.size,
|
||||
label: "Radius",
|
||||
});
|
||||
|
||||
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<typeof AnimatedEntities>
|
||||
) {
|
||||
const animatedProperties: z.input<typeof AnimatedProperties> = [];
|
||||
|
||||
animatedEntities.forEach((aEnt) => {
|
||||
animatedProperties.push(...getAnimatedPropertiesByAnimatedEntity(aEnt));
|
||||
});
|
||||
}
|
||||
|
||||
10
app/src/primitives/AnimatedProperty.ts
Normal file
10
app/src/primitives/AnimatedProperty.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from "zod";
|
||||
import { AnimatedValue } from "./Values";
|
||||
|
||||
export const AnimatedProperty = z.object({
|
||||
propertyPath: z.string(),
|
||||
animatedValue: AnimatedValue,
|
||||
label: z.string(),
|
||||
});
|
||||
|
||||
export const AnimatedProperties = z.array(AnimatedProperty);
|
||||
@@ -1,7 +1,9 @@
|
||||
import { z } from "zod";
|
||||
import { Interpolation } from "./Interpolation";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
export const Keyframe = z.object({
|
||||
id: z.string().uuid(),
|
||||
value: z.number(),
|
||||
offset: z.number(),
|
||||
interpolation: z.optional(Interpolation),
|
||||
|
||||
@@ -1,29 +1,57 @@
|
||||
import { z } from "zod";
|
||||
import { Keyframes } from "./Keyframe";
|
||||
import { Interpolation } from "./Interpolation";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
export const Vec2 = z.array(z.number()).length(2);
|
||||
export const Vec3 = z.array(z.number()).length(3);
|
||||
|
||||
const ValueTypeOptions = ["Vec2", "Vec3", "Number"] as const;
|
||||
|
||||
export const ValueType = z.enum(ValueTypeOptions);
|
||||
|
||||
export const AnimatedNumber = z.object({
|
||||
keyframes: Keyframes,
|
||||
type: z.literal(ValueType.Enum.Number),
|
||||
});
|
||||
|
||||
export const AnimatedVec2 = z.object({
|
||||
keyframes: z.array(AnimatedNumber).length(2),
|
||||
type: z.literal(ValueType.Enum.Vec2),
|
||||
});
|
||||
|
||||
export const AnimatedVec3 = z.object({
|
||||
keyframes: z.array(AnimatedNumber).length(3),
|
||||
type: z.literal(ValueType.Enum.Vec3),
|
||||
});
|
||||
|
||||
export const AnimatedTransform = z.object({
|
||||
type: z.literal("Transform"),
|
||||
/** Translates by the given animated vec2 */
|
||||
translate: AnimatedVec2,
|
||||
/** Skews by the given animated vec2 */
|
||||
skew: AnimatedVec2,
|
||||
/** Rotates by the given animated vec3 */
|
||||
rotate: AnimatedVec3,
|
||||
/** Scales on the x and y axis by the given animated vec2 */
|
||||
scale: AnimatedVec2,
|
||||
});
|
||||
|
||||
export const AnimatedValue = z.discriminatedUnion("type", [
|
||||
AnimatedNumber,
|
||||
AnimatedVec2,
|
||||
AnimatedVec3,
|
||||
AnimatedTransform,
|
||||
]);
|
||||
|
||||
export function staticAnimatedNumber(
|
||||
number: number
|
||||
): z.infer<typeof AnimatedNumber> {
|
||||
return {
|
||||
type: ValueType.Enum.Number,
|
||||
keyframes: {
|
||||
values: [
|
||||
{
|
||||
id: uuid(),
|
||||
interpolation: {
|
||||
type: "Linear",
|
||||
},
|
||||
@@ -40,6 +68,7 @@ export function staticAnimatedVec2(
|
||||
y: number
|
||||
): z.infer<typeof AnimatedVec2> {
|
||||
return {
|
||||
type: ValueType.Enum.Vec2,
|
||||
keyframes: [staticAnimatedNumber(x), staticAnimatedNumber(y)],
|
||||
};
|
||||
}
|
||||
@@ -48,8 +77,9 @@ export function staticAnimatedVec3(
|
||||
x: number,
|
||||
y: number,
|
||||
z: number
|
||||
): z.infer<typeof AnimatedVec2> {
|
||||
): z.infer<typeof AnimatedVec3> {
|
||||
return {
|
||||
type: ValueType.Enum.Vec3,
|
||||
keyframes: [
|
||||
staticAnimatedNumber(x),
|
||||
staticAnimatedNumber(y),
|
||||
|
||||
Reference in New Issue
Block a user