Skip to content
Merged
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
22 changes: 12 additions & 10 deletions build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,18 @@ function build({ x64, arm64 } = options) {
win: {
target: "nsis",
forceCodeSigning: args.noSign ? false : true,
signtoolOptions: {
sign: (configuration) => {
if (configuration.path) {
execSync(`smctl.exe sign --keypair-alias=${process.env.KEYPAIR_ALIAS} --input "${String(configuration.path)}"`);
}
},
publisherName: "cesharpe",
signingHashAlgorithms: ["sha256"],
rfc3161TimeStampServer: "http://timestamp.digicert.com",
},
signtoolOptions: args.noSign
? undefined
: {
sign: (configuration) => {
if (configuration.path) {
execSync(`smctl.exe sign --keypair-alias=${process.env.KEYPAIR_ALIAS} --input "${String(configuration.path)}"`);
}
},
publisherName: "cesharpe",
signingHashAlgorithms: ["sha256"],
rfc3161TimeStampServer: "http://timestamp.digicert.com",
},
},
fileAssociations: [
{
Expand Down
117 changes: 117 additions & 0 deletions editor/src/editor/layout/cinematic/curves.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Component, MouseEvent } from "react";

import { Vector2 } from "babylonjs";
import { ICinematicTrack } from "babylonjs-editor-tools";

import { isDomElementDescendantOf } from "../../../tools/dom";

import { CinematicEditor } from "./editor";

import { CinematicEditorCurvesRoot } from "./curves/root";

export interface ICinematicEditorCurvesProps {
scale: number;
currentTime: number;

selectedTrack: ICinematicTrack | null;

cinematicEditor: CinematicEditor;
}

export interface ICinematicEditorCurvesState {
translation: Vector2;
}

export class CinematicEditorCurves extends Component<ICinematicEditorCurvesProps, ICinematicEditorCurvesState> {
private _divRef: HTMLDivElement | null = null;

public constructor(props: ICinematicEditorCurvesProps) {
super(props);

this.state = {
translation: Vector2.Zero(),
};
}

public render(): React.ReactNode {
return (
<div
ref={(r) => (this._divRef = r)}
className={`
relative flex flex-col flex-1 w-full min-h-fit h-full overflow-x-auto overflow-y-hidden
${this.props.cinematicEditor.state.editType !== "curves" ? "hidden pointer-events-none" : ""}
`}
onMouseDown={(ev) => this._handleMainDivPointerDown(ev)}
>
<CinematicEditorCurvesRoot scale={this.props.scale} translation={this.state.translation} cinematicEditor={this.props.cinematicEditor} />

<div
className="absolute w-[1px] ml-2 mt-10 bg-muted h-full pointer-events-none"
style={{
left: `${this.props.currentTime * this.props.scale + this.state.translation.x}px`,
}}
>
<div
className="absolute w-7 h-7 rotate-45 -translate-x-1/2 -translate-y-8 bg-muted"
style={{
mask: "linear-gradient(135deg, transparent 0%, transparent 50%, black 50%, black 100%)",
}}
/>
</div>
</div>
);
}

private _handleMainDivPointerDown(event: MouseEvent<HTMLDivElement>): void {
if (event.button !== 0 || !isDomElementDescendantOf(event.nativeEvent.target as HTMLElement, this._divRef!)) {
return;
}

document.body.style.cursor = "ew-resize";

let mouseUpListener: (event: globalThis.MouseEvent) => void;
let mouseMoveListener: (event: globalThis.MouseEvent) => void;

let moving = false;
let clientX: number | null = null;

const startPosition = (event.nativeEvent.offsetX - this.state.translation.x) / this.props.scale;

this.props.cinematicEditor.createTemporaryAnimationGroup();
this.props.cinematicEditor.setCurrentTime(startPosition);

document.body.addEventListener(
"mousemove",
(mouseMoveListener = (ev) => {
if (clientX === null) {
clientX = ev.clientX;
}

const delta = clientX - ev.clientX;
if (moving || Math.abs(delta) > 5 * devicePixelRatio) {
moving = true;
} else {
return;
}

const currentTime = Math.round(Math.max(0, startPosition - delta / this.props.scale));

this.props.cinematicEditor.setCurrentTime(currentTime);
})
);

document.body.addEventListener(
"mouseup",
(mouseUpListener = (ev) => {
ev.stopPropagation();

document.body.style.cursor = "auto";

document.body.removeEventListener("mouseup", mouseUpListener);
document.body.removeEventListener("mousemove", mouseMoveListener);

this.props.cinematicEditor.disposeTemporaryAnimationGroup();
})
);
}
}
155 changes: 155 additions & 0 deletions editor/src/editor/layout/cinematic/curves/curve.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { IAnimationKey } from "babylonjs";
import { ICinematicKey, ICinematicKeyCut } from "babylonjs-editor-tools";

import { getKeyFrame } from "../timelines/tools";

import { CinematicEditor } from "../editor";

import { convertKeysToBezier, valueToSVGY } from "./tools/tools";
import { getEditablePropertyValue, ICinematicEditorEditableProperty } from "./tools/property";

import { CinematicEditorCurveHandle } from "./handle";
import { CinematicEditorPropertyPoint } from "./point";

export interface ICinematicEditorPropertyCubeProps {
color: string;
height: number;

scale: number;
yScale: number;

drawPoint: boolean;
drawHandles: boolean;

cinematicKey: ICinematicKey | ICinematicKeyCut;
nextCinematicKey: ICinematicKey | ICinematicKeyCut;

editableAnimationKey: IAnimationKey;
nextEditableAnimationKey: IAnimationKey;

editableProperty: ICinematicEditorEditableProperty;
nextEditableProperty: ICinematicEditorEditableProperty;

editableTangentProperty?: ICinematicEditorEditableProperty;
nextEditableTangentProperty?: ICinematicEditorEditableProperty;

cinematicEditor: CinematicEditor;
}

export function CinematicEditorPropertyCurve(props: ICinematicEditorPropertyCubeProps) {
const value = getEditablePropertyValue(props.editableProperty);
const nextValue = getEditablePropertyValue(props.nextEditableProperty);

const { p0, p1, c1, c2 } = convertKeysToBezier({
frame1: getKeyFrame(props.cinematicKey),
frame2: getKeyFrame(props.nextCinematicKey),
value1: value * props.yScale,
value2: nextValue * props.yScale,
outTangent: props.editableTangentProperty ? getEditablePropertyValue(props.editableTangentProperty) * props.yScale : 0,
inTangent: props.nextEditableTangentProperty ? getEditablePropertyValue(props.nextEditableTangentProperty) * props.yScale : 0,
});

const computedP0 = [p0[0], valueToSVGY(p0[1], props.height)] as [number, number];
const computedP1 = [p1[0], valueToSVGY(p1[1], props.height)] as [number, number];
const computedC1 = [c1[0], valueToSVGY(c1[1], props.height)] as [number, number];
const computedC2 = [c2[0], valueToSVGY(c2[1], props.height)] as [number, number];

const d = `
M ${computedP0[0]},${computedP0[1]}
C ${computedC1[0]},${computedC1[1]}
${computedC2[0]},${computedC2[1]}
${computedP1[0]},${computedP1[1]}
`;

return (
<>
<path d={d} className={`fill-none ${props.color} pointer-events-none`} strokeWidth={2 / props.scale} />

{props.drawPoint && (
<CinematicEditorPropertyPoint
cx={computedP0[0]}
cy={computedP0[1]}
scale={props.scale}
yScale={props.yScale}
cinematicKey={props.cinematicKey}
editableProperty={props.editableProperty}
animationKey={props.editableAnimationKey}
cinematicEditor={props.cinematicEditor}
/>
)}

<CinematicEditorPropertyPoint
cx={computedP1[0]}
cy={computedP1[1]}
scale={props.scale}
yScale={props.yScale}
cinematicKey={props.nextCinematicKey}
editableProperty={props.nextEditableProperty}
animationKey={props.nextEditableAnimationKey}
cinematicEditor={props.cinematicEditor}
/>

{props.editableTangentProperty && props.drawHandles && (
<>
<line
x1={computedP0[0]}
y1={computedP0[1]}
x2={computedC1[0]}
y2={computedC1[1]}
className={`${props.color} pointer-events-none`}
strokeWidth={2 / props.scale}
strokeDasharray={4 / props.scale}
/>

<CinematicEditorCurveHandle
scale={props.scale}
yScale={props.yScale}
height={props.height}
strokeColor={props.color}
c1={computedC1}
c2={computedC2}
tangentType="out"
cinematicKey={props.cinematicKey}
nextCinematicKey={props.nextCinematicKey}
editableProperty={props.editableProperty}
nextEditableProperty={props.nextEditableProperty}
editableTangentProperty={props.editableTangentProperty}
nextEditableTangentProperty={props.nextEditableTangentProperty}
cinematicEditor={props.cinematicEditor}
/>
</>
)}

{props.nextEditableTangentProperty && props.drawHandles && (
<>
<line
x1={computedP1[0]}
y1={computedP1[1]}
x2={computedC2[0]}
y2={computedC2[1]}
className={`${props.color} pointer-events-none`}
strokeWidth={2 / props.scale}
strokeDasharray={4 / props.scale}
/>

<CinematicEditorCurveHandle
scale={props.scale}
yScale={props.yScale}
height={props.height}
strokeColor={props.color}
c1={computedC1}
c2={computedC2}
tangentType="in"
cinematicKey={props.cinematicKey}
nextCinematicKey={props.nextCinematicKey}
editableProperty={props.editableProperty}
nextEditableProperty={props.nextEditableProperty}
editableTangentProperty={props.editableTangentProperty}
nextEditableTangentProperty={props.nextEditableTangentProperty}
cinematicEditor={props.cinematicEditor}
/>
</>
)}
</>
);
}
Loading