Skip to content

Commit

Permalink
Merge branch 'dev-2.0' into dev-2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Vaivaswat2244 authored Jan 26, 2025
2 parents 0ce4e89 + 23b90ec commit 9cfef5a
Show file tree
Hide file tree
Showing 182 changed files with 3,007 additions and 3,703 deletions.
5,338 changes: 2,177 additions & 3,161 deletions docs/parameterData.json

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions src/color/creating_reading.js
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,61 @@ function creatingReading(p5, fn){
// p5._validateParameters('lerpColor', arguments);
return c1.lerp(c2, amt, this._renderer.states.colorMode);
};

/**
* Blends multiple colors to find a color between them.
*
* The `amt` parameter specifies the amount to interpolate between the color
* stops which are colors at each `amt` value "location" with `amt` values
* that are between 2 color stops interpolating between them based on its relative
* distance to both.
*
* The way that colors are interpolated depends on the current
* <a href="#/colorMode">colorMode()</a>.
*
* @method paletteLerp
* @param {[p5.Color|String|Number|Number[], Number][]} colors_stops color stops to interpolate from
* @param {Number} amt number to use to interpolate relative to color stops
* @return {p5.Color} interpolated color.
*
* @example
* <div>
* <code>
* function setup() {
* createCanvas(400, 400);
* }
*
* function draw() {
* // The background goes from white to red to green to blue fill
* background(paletteLerp([
* ['white', 0],
* ['red', 0.05],
* ['green', 0.25],
* ['blue', 1]
* ], millis() / 10000 % 1));
* }
* </code>
* </div>
*/
fn.paletteLerp = function(color_stops, amt) {
const first_color_stop = color_stops[0];
if (amt < first_color_stop[1])
return this.color(first_color_stop[0]);

for (let i = 1; i < color_stops.length; i++) {
const color_stop = color_stops[i];
if (amt < color_stop[1]) {
const prev_color_stop = color_stops[i - 1];
return this.lerpColor(
this.color(prev_color_stop[0]),
this.color(color_stop[0]),
(amt - prev_color_stop[1]) / (color_stop[1] - prev_color_stop[1])
);
}
}

return this.color(color_stops[color_stops.length - 1][0]);
};
}

export default creatingReading;
Expand Down
6 changes: 3 additions & 3 deletions src/core/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,7 @@ export const FLOAT = 'float';
export const HALF_FLOAT = 'half-float';

/**
* The `splineEnds` mode where splines curve through
* The `splineProperty('ends')` mode where splines curve through
* their first and last points.
* @typedef {unique symbol} INCLUDE
* @property {INCLUDE} INCLUDE
Expand All @@ -1368,7 +1368,7 @@ export const HALF_FLOAT = 'half-float';
export const INCLUDE = Symbol('include');

/**
* The `splineEnds` mode where the first and last points in a spline
* The `splineProperty('ends')` mode where the first and last points in a spline
* affect the direction of the curve, but are not rendered.
* @typedef {unique symbol} EXCLUDE
* @property {EXCLUDE} EXCLUDE
Expand All @@ -1377,7 +1377,7 @@ export const INCLUDE = Symbol('include');
export const EXCLUDE = Symbol('exclude');

/**
* The `splineEnds` mode where the spline loops back to its first point.
* The `splineProperty('ends')` mode where the spline loops back to its first point.
* Only used internally.
* @typedef {unique symbol} JOIN
* @property {JOIN} JOIN
Expand Down
65 changes: 39 additions & 26 deletions src/core/friendly_errors/param_validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ function validateParams(p5, fn, lifecycles) {
// const p5Constructors = {};
// NOTE: This is a tempt fix for unit test but is not correct
// Attaced constructors are `undefined`
const p5Constructors = Object.keys(dataDoc).reduce((acc, val) => {
if (val !== 'p5') {
const className = val.substring(3);
acc[className] = p5[className];
const p5Constructors = Object.keys(p5).reduce((acc, val) => {
if (
val.match(/^[A-Z]/) && // Starts with a capital
!val.match(/^[A-Z][A-Z0-9]*$/) && // Is not an all caps constant
p5[val] instanceof Function // Is a function
) {
acc[val] = p5[val];
}
return acc;
}, {});
Expand Down Expand Up @@ -125,18 +128,6 @@ function validateParams(p5, fn, lifecycles) {
* @returns {z.ZodSchema} Zod schema
*/
fn.generateZodSchemasForFunc = function (func) {
// A special case for `p5.Color.paletteLerp`, which has an unusual and
// complicated function signature not shared by any other function in p5.
if (func === 'p5.Color.paletteLerp') {
return z.tuple([
z.array(z.tuple([
z.instanceof(p5.Color),
z.number()
])),
z.number()
]);
}

const { funcName, funcClass } = extractFuncNameAndClass(func);
let funcInfo = dataDoc[funcClass][funcName];

Expand All @@ -149,18 +140,27 @@ function validateParams(p5, fn, lifecycles) {

// Returns a schema for a single type, i.e. z.boolean() for `boolean`.
const generateTypeSchema = type => {
if (!type) return z.any();

const isArray = type.endsWith('[]');
const baseType = isArray ? type.slice(0, -2) : type;

let typeSchema;

// Type only contains uppercase letters and underscores -> type is a
// constant. Note that because we're ultimately interested in the value of
// Check for constants. Note that because we're ultimately interested in the value of
// the constant, mapping constants to their values via `constantsMap` is
// necessary.
if (/^[A-Z_]+$/.test(baseType)) {
if (baseType in constantsMap) {
typeSchema = z.literal(constantsMap[baseType]);
}
// Some more constants are attached directly to p5.prototype, e.g. by addons:
else if (baseType.match(/^[A-Z][A-Z0-9]*$/) && baseType in fn) {
typeSchema = z.literal(fn[baseType]);
}
// Function types
else if (baseType.startsWith('function')) {
typeSchema = z.function();
}
// All p5 objects start with `p5` in the documentation, i.e. `p5.Camera`.
else if (baseType.startsWith('p5')) {
const className = baseType.substring(baseType.indexOf('.') + 1);
Expand All @@ -169,6 +169,19 @@ function validateParams(p5, fn, lifecycles) {
// For primitive types and web API objects.
else if (schemaMap[baseType]) {
typeSchema = schemaMap[baseType];
}
// Tuple types
else if (baseType.startsWith('[') && baseType.endsWith(']')) {
typeSchema = z.tuple(
baseType
.slice(1, -1)
.split(/, */g)
.map(entry => generateTypeSchema(entry))
);
}
// JavaScript classes, e.g. Request
else if (baseType.match(/^[A-Z]/) && baseType in window) {
typeSchema = z.instanceof(window[baseType]);
} else {
throw new Error(`Unsupported type '${type}' in parameter validation. Please report this issue.`);
}
Expand All @@ -179,8 +192,8 @@ function validateParams(p5, fn, lifecycles) {
// Generate a schema for a single parameter. In the case where a parameter can
// be of multiple types, `generateTypeSchema` is called for each type.
const generateParamSchema = param => {
const isOptional = param.endsWith('?');
param = param.replace(/\?$/, '');
const isOptional = param?.endsWith('?');
param = param?.replace(/\?$/, '');

let schema;

Expand All @@ -193,7 +206,7 @@ function validateParams(p5, fn, lifecycles) {
// our constants sometimes have numeric or non-primitive values.
// 2) In some cases, the type can be constants or strings, making z.enum()
// insufficient for the use case.
if (param.includes('|')) {
if (param?.includes('|')) {
const types = param.split('|');
schema = z.union(types
.map(t => generateTypeSchema(t))
Expand All @@ -218,11 +231,11 @@ function validateParams(p5, fn, lifecycles) {
// combinations that are valid for all numbers of parameters.
const generateOverloadCombinations = params => {
// No optional parameters, return the original parameter list right away.
if (!params.some(p => p.endsWith('?'))) {
if (!params.some(p => p?.endsWith('?'))) {
return [params];
}

const requiredParamsCount = params.filter(p => !p.endsWith('?')).length;
const requiredParamsCount = params.filter(p => p === null || !p.endsWith('?')).length;
const result = [];

for (let i = requiredParamsCount; i <= params.length; i++) {
Expand Down Expand Up @@ -332,7 +345,7 @@ function validateParams(p5, fn, lifecycles) {
/**
* Prints a friendly error message after parameter validation, if validation
* has failed.
*
*
* @method _friendlyParamError
* @private
* @param {z.ZodError} zodErrorObj - The Zod error object containing validation errors.
Expand Down Expand Up @@ -423,7 +436,7 @@ function validateParams(p5, fn, lifecycles) {

// Generates a link to the documentation based on the given function name.
// TODO: Check if the link is reachable before appending it to the error
// message.
// message.
const generateDocumentationLink = (func) => {
const { funcName, funcClass } = extractFuncNameAndClass(func);
const p5BaseUrl = 'https://p5js.org/reference';
Expand Down
Loading

0 comments on commit 9cfef5a

Please sign in to comment.