Skip to content

Commit

Permalink
recompute_if() and dangerous()
Browse files Browse the repository at this point in the history
  • Loading branch information
Robin Fernandes committed Jun 27, 2023
1 parent a7553ea commit 923d25d
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 13 deletions.
5 changes: 3 additions & 2 deletions src/parseq-lang/parseq-lang-ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { frameToBeat, frameToSec } from '../utils/maths';
import { InterpolationType, TimeSeries } from './parseq-timeseries';
//@ts-ignore
import functionLibrary, { ParseqFunction } from './parseq-lang-functions';
import { ParseqRenderedFrames } from '../ParseqUI';

type InputLocation = {
line: number | undefined;
Expand Down Expand Up @@ -36,6 +37,7 @@ export type InvocationContext = {
ts: TimeSeries;
}] | [],
promptType?: boolean;
rendered_frames?: ParseqRenderedFrames;
}

export function getNextKeyframe(ctx: InvocationContext): number {
Expand Down Expand Up @@ -116,9 +118,8 @@ export abstract class ParseqAstNode {
return this.value;
}

public getOrComputeState(key: string, compute: () => object): object {
public getOrComputeState(key: string, compute: () => object): object | undefined {
if (this.nodeState.has(key)) {
//@ts-ignore - we know this is an object
return this.nodeState.get(key);
} else {
const value = compute();
Expand Down
6 changes: 5 additions & 1 deletion src/parseq-lang/parseq-lang-functions-curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,16 +257,20 @@ const functionLibrary: { [key: string]: ParseqFunction } = {
{ description: "control point y2", names: ["y2"], type: "number", required: false, default: 1 },
{ description: "starting y position", names: ["from", "start", "s"], type: "number", required: false, default: (ctx) => getActiveKeyframeValue(ctx) },
{ description: "ending y position", names: ["to", "end", "t"], type: "number", required: false, default: (ctx) => getNextKeyframeValue(ctx) },
{ description: "ending y position as a delta of starting position", names: ["d", "delta"], type: "number", required: false, default: 0 },
{ description: "duration of the bezier curve in frames", names: ["span", "in", "s"], type: "number", required: false, default: (ctx) => getNextKeyframe(ctx) - ctx.activeKeyframe },
{ description: "offset", names: ["offset","os"], type: "number", required: false, default: 2 },
{ description: "curve type (overriddes x1, y1, x2, y2 with preset values)", names: ["curve","c"], type: "string", required: false, default: "" },
],

call: (ctx, args) => {
let [x1, y1, x2, y2, from, to, span, offset, curve] = [Number(args[0]), Number(args[1]), Number(args[2]), Number(args[3]), Number(args[4]), Number(args[5]), Number(args[6]), Number(args[7]), String(args[8])];
let [x1, y1, x2, y2, from, to, delta, span, offset, curve] = [Number(args[0]), Number(args[1]), Number(args[2]), Number(args[3]), Number(args[4]), Number(args[5]), Number(args[6]), Number(args[7]), Number(args[8]), String(args[9])];
if (curve) {
[x1, y1, x2, y2] = curveNameToControlPoints(curve);
}
if (delta) {
to = from + delta;
}

return bezier(x1, y1, x2, y2, from, to, span, offset, ctx)
}
Expand Down
20 changes: 12 additions & 8 deletions src/parseq-lang/parseq-lang-functions-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ function frameOfNextMatch(ctx: InvocationContext, pattern: string) {
const info_match_prev : ParseqFunction = {
description: "Returns the frame number of the last keyframe that matched the regex, or -1 if none.",
argDefs: [
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" }
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" },
{ description: "default if no previous match", names: ["default", "d"], type: "string", required: false, default: -1 }
],
call: (ctx, args) => {
const pattern = String(args[0]);
const prevMatch = frameOfPrevMatch(ctx, pattern);
return prevMatch ? prevMatch.frame : -1;
return prevMatch ? prevMatch.frame : Number(args[1]);
}
};

Expand Down Expand Up @@ -56,38 +57,41 @@ const functionLibrary: { [key: string]: ParseqFunction } = {
"info_match_next": {
description: "Returns the frame number of the next keyframe that matched the regex, or -1 if none.",
argDefs: [
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" }
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" },
{ description: "default if no next match", names: ["default", "d"], type: "string", required: false, default: -1 }
],
call: (ctx, args) => {
const pattern = String(args[0]);
const nextMatch = frameOfNextMatch(ctx, pattern)
return nextMatch ? nextMatch.frame : -1;
return nextMatch ? nextMatch.frame : Number(args[1]);
}
},

"info_match_gap": {
description: "Returns the number of frames between the previous and next match (equivalent to info_match_next()-info_match_prev()), or -1 if not between matches.",
argDefs: [
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" }
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" },
{ description: "default if not between matches", names: ["default", "d"], type: "string", required: false, default: -1 }
],
call: (ctx, args) => {
const pattern = String(args[0]);
const prevMatch = frameOfPrevMatch(ctx, pattern);
const nextMatch = frameOfNextMatch(ctx, pattern)
return (nextMatch && prevMatch) ? (nextMatch.frame - prevMatch.frame) : -1;
return (nextMatch && prevMatch) ? (nextMatch.frame - prevMatch.frame) : Number(args[1]);
}
},

"info_match_progress": {
description: "Returns a number between 0 and 1 reprenting how far the current frame is along the gap between (equivalent to (f-info_match_prev()/info_match_gap()), or -1 if not between matches.",
argDefs: [
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" }
{ description: "regex", names: ["regex", "r"], type: "string", required: true, default: "" },
{ description: "default if not between matches", names: ["default", "d"], type: "string", required: false, default: -1 }
],
call: (ctx, args) => {
const pattern = String(args[0]);
const prevMatch = frameOfPrevMatch(ctx, pattern);
const nextMatch = frameOfNextMatch(ctx, pattern)
return (nextMatch && prevMatch) ? (ctx.frame - prevMatch.frame) / (nextMatch.frame - prevMatch.frame) : -1;
return (nextMatch && prevMatch) ? (ctx.frame - prevMatch.frame) / (nextMatch.frame - prevMatch.frame) : Number(args[1]);
}
}

Expand Down
48 changes: 47 additions & 1 deletion src/parseq-lang/parseq-lang-functions-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,53 @@ const functionLibrary: { [key: string]: ParseqFunction } = {
const wholeBeat = Math.floor(frameToBeat(Number(args[0]), ctx.FPS, ctx.BPM));
return rounding(beatToFrame(wholeBeat, ctx.FPS, ctx.BPM));
}
}
},
"recompute_if": {
description: "If the supplied condition is true, return the second param, else return the value of the second param when condition was last true. If condition is false and has never been true, return -1 or overridden default.",
argDefs: [
{ description: "condition", names: ["if"], type: "number", required: true, default: 0},
{ description: "compute", names: ["compute", "c"], type: "number", required: true, default: 0},
{ description: "default", names: ["default", "d"], type: "number", required: false, default: -1},
// Need to think about this one some more – it won't be auto-recomputed if referenced directly.
//{ description: "varname", names: ["varname", "v"], type: "string", required: false, default: 'r' },
],
call: (ctx, args) => {
const condition = Number(args[0]);
const newValue = Number(args[1]);
const def = Number(args[2]);
const stored = ctx.activeNode?.getOrComputeState('stored_var', () => ({ stored_var: newValue })) as { stored_var: number };
let retval;
if (condition > 0) {
ctx.activeNode?.setState('stored_var', { stored_var: newValue });
retval = newValue;
} else if (stored?.stored_var !== undefined) {
retval = stored.stored_var;
} else {
retval = def;
}
return retval;
}
},
"dangerous": {
description: "Get value of a field at a given frame. Beware of cycles (there's no protection from them)",
argDefs: [
{ description: "field name", names: ["name", "n"], type: "string", required: true, default: 0},
{ description: "frame", names: ["frame", "f"], type: "number", required: false, default: (ctx) => ctx.frame},
],
call: (ctx, args) => {

console.log(ctx.rendered_frames![Number(args[1])]);

if (ctx.rendered_frames
&& ctx.rendered_frames[Number(args[1])]
&& ctx.rendered_frames[Number(args[1])][args[0]]) {
return ctx.rendered_frames[Number(args[1])][args[0]];
} else {
return -1;
}

}
}
}

export default functionLibrary;
4 changes: 3 additions & 1 deletion src/parseq-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const parseqRender = (input: ParseqPersistableState): { renderedData: Ren
var all_frame_numbers = Array.from(Array(lastKeyFrame.frame - firstKeyFrame.frame + 1).keys()).map((i) => i + firstKeyFrame.frame);
const graphData: GraphableData = {};
managedFields.forEach((field) => {
console.log(field);

graphData[field] = [];

Expand Down Expand Up @@ -147,7 +148,8 @@ export const parseqRender = (input: ParseqPersistableState): { renderedData: Ren
BPM: options.bpm,
computed_values: prev_computed_values,
variableMap: new Map([["prev_computed_value", (frame>0) ? prev_computed_values[frame-1] : 0]]),
timeSeries: timeSeries
timeSeries: timeSeries,
rendered_frames
}
computed_value = interpolator.invoke(ctx);
stats.invokeEvents++;
Expand Down

0 comments on commit 923d25d

Please sign in to comment.