add effects primitives

add blur effect
add default spring values
improve values ui
This commit is contained in:
Enrico Bühler 2023-06-18 14:34:36 +02:00
parent fcd3afa3f2
commit c67e023b5c
7 changed files with 110 additions and 50 deletions

View File

@ -9,7 +9,7 @@ import {
import { Paint, PaintStyle, PaintStyleType } from "primitives/Paint"; import { Paint, PaintStyle, PaintStyleType } from "primitives/Paint";
import { FC } from "react"; import { FC } from "react";
import { z } from "zod"; import { z } from "zod";
import { AnimatedVec2Properties, ColorProperties } from "./Values"; import { ColorProperties } from "./Values";
import { PropertiesProps } from "./common"; import { PropertiesProps } from "./common";
import { useFontsStore } from "stores/fonts.store"; import { useFontsStore } from "stores/fonts.store";
import { import {
@ -57,7 +57,7 @@ export const PaintProperties: FC<PaintPropertiesProps> = ({
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Choose a paint style" /> <SelectValue placeholder="Choose a paint style" />
</SelectTrigger> </SelectTrigger>
<SelectContent className="overflow-hidden"> <SelectContent id="paint-style-type" className="overflow-hidden">
{Object.keys(PaintStyleType.Values).map((paintStyleType) => ( {Object.keys(PaintStyleType.Values).map((paintStyleType) => (
<SelectItem value={paintStyleType}>{paintStyleType}</SelectItem> <SelectItem value={paintStyleType}>{paintStyleType}</SelectItem>
))} ))}

View File

@ -4,12 +4,19 @@ import { FC } from "react";
import { z } from "zod"; import { z } from "zod";
import { produce } from "immer"; import { produce } from "immer";
import { Interpolation, InterpolationType } from "primitives/Interpolation"; import { Interpolation, InterpolationType } from "primitives/Interpolation";
import { Color } from "primitives/Paint"; import { Color, PaintStyle, PaintStyleType } from "primitives/Paint";
import { parseCssColor } from "@tempblade/common"; import { parseCssColor } from "@tempblade/common";
import { rgbToHex } from "utils"; import { rgbToHex } from "utils";
import { SpringInterpolation } from "primitives/Interpolation"; import { SpringInterpolation } from "primitives/Interpolation";
import FloatInput from "components/Inputs/FloatInput"; import FloatInput from "components/Inputs/FloatInput";
import { Keyframe } from "primitives/Keyframe"; import { Keyframe } from "primitives/Keyframe";
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
} from "components/Inputs/Select";
const SpringInterpolationProperties: FC< const SpringInterpolationProperties: FC<
PropertiesProps<z.input<typeof SpringInterpolation>> PropertiesProps<z.input<typeof SpringInterpolation>>
@ -25,22 +32,29 @@ export const InterpolationProperties: FC<
<label className="label" htmlFor="interpolation-type"> <label className="label" htmlFor="interpolation-type">
Interpolation Type Interpolation Type
</label> </label>
<select <Select
id="interpolation-type" defaultValue={entity.type}
onChange={(e) => { onValueChange={(value) => {
onUpdate({ if (entity.type !== value) {
...entity, const interpolation = { type: value };
type: e.target.value as any,
}); const parsedInterpolation = Interpolation.parse(interpolation);
onUpdate(parsedInterpolation);
}
}} }}
value={entity.type}
> >
{Object.keys(InterpolationType.Values).map((key) => ( <SelectTrigger>
<option key={key} value={key}> <SelectValue placeholder="Choose an interpolation type" />
{key} </SelectTrigger>
</option> <SelectContent id="interpolation-type" className="overflow-hidden">
))} {Object.keys(InterpolationType.Values).map((interpolationType) => (
</select> <SelectItem key={interpolationType} value={interpolationType}>
{interpolationType}
</SelectItem>
))}
</SelectContent>
</Select>
</fieldset> </fieldset>
); );
}; };
@ -129,35 +143,35 @@ export const ColorProperties: FC<
> = ({ entity, onUpdate, mode = "Picker" }) => { > = ({ entity, onUpdate, mode = "Picker" }) => {
if (mode === "Picker") { if (mode === "Picker") {
return ( return (
<label className="flex flex-col items-start"> <fieldset>
<span className="label">Color</span> <label htmlFor="color">Color</label>
<div className="flex flex-row gap-3"> <input
<input id="color"
value={rgbToHex(entity.value[0], entity.value[1], entity.value[2])} value={rgbToHex(entity.value[0], entity.value[1], entity.value[2])}
type="color" type="color"
style={{ style={{
width: 32, border: "none",
height: 32, width: 32,
backgroundColor: rgbToHex( height: 32,
entity.value[0], backgroundColor: rgbToHex(
entity.value[1], entity.value[0],
entity.value[2] entity.value[1],
), entity.value[2]
}} ),
onChange={(e) => }}
onUpdate( onChange={(e) =>
produce(entity, (draft) => { onUpdate(
const color = parseCssColor(e.target.value); produce(entity, (draft) => {
const color = parseCssColor(e.target.value);
if (color) { if (color) {
draft.value = [...color, 1.0]; draft.value = [...color, 1.0];
} }
}) })
) )
} }
/> />
</div> </fieldset>
</label>
); );
} }

View File

View File

@ -0,0 +1,27 @@
import { Canvas, CanvasKit, Surface } from "canvaskit-wasm";
import { BlurEffectLayer } from "primitives/Effects";
import { z } from "zod";
export default function applyBlur(
CanvasKit: CanvasKit,
canvas: Canvas,
surface: Surface,
options: z.input<typeof BlurEffectLayer>
) {
const image = surface.makeImageSnapshot();
if (image) {
const blurFilter = CanvasKit.ImageFilter.MakeBlur(
options.amountX,
options.amountY,
CanvasKit.TileMode[options.tileMode],
null
);
const paint = new CanvasKit.Paint();
paint.setImageFilter(blurFilter);
canvas.drawImage(image, 0, 0, paint);
}
}

View File

@ -0,0 +1,19 @@
import { z } from "zod";
export const EffectTypeOptions = ["Blur", "Erode", "Displace"] as const;
export const TileModeOptions = ["Clamp", "Decal", "Mirror", "Repeat"] as const;
export const EffectType = z.enum(EffectTypeOptions);
export const TileMode = z.enum(TileModeOptions);
export const EffectLayer = z.object({
entityId: z.string().uuid(),
});
export const BlurEffectLayer = EffectLayer.extend({
type: z.literal(EffectType.enum.Blur),
amountX: z.number().min(0),
amountY: z.number().min(0),
tileMode: TileMode,
});

View File

@ -36,13 +36,13 @@ export const LinearInterpolation = z.object({
export const EasingFunctionInterpolation = z.object({ export const EasingFunctionInterpolation = z.object({
type: z.literal(InterpolationType.Enum.EasingFunction), type: z.literal(InterpolationType.Enum.EasingFunction),
easing_function: EasingFunction, easing_function: EasingFunction.default("CircOut"),
}); });
export const SpringInterpolation = z.object({ export const SpringInterpolation = z.object({
mass: z.number(), mass: z.number().default(1),
damping: z.number(), damping: z.number().default(15),
stiffness: z.number(), stiffness: z.number().default(200),
type: z.literal(InterpolationType.Enum.Spring), type: z.literal(InterpolationType.Enum.Spring),
}); });

View File

@ -131,7 +131,7 @@ label {
} }
fieldset { fieldset {
@apply mb-2 flex flex-col items-start w-16; @apply mb-2 flex flex-col items-start;
} }
:root { :root {