Skip to content

[p5.js 2.0 Bug Report]: [p5.strands] && and || in if conditions not working correctly #8358

@davepagurek

Description

@davepagurek

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build process
  • Unit testing
  • Internationalization
  • Friendly errors
  • Other (specify if possible)

p5.js version

2.1.2

Web browser and version

Any

Operating system

Any

Steps to reproduce this

Steps:

  1. Create a p5.strands shader
  2. Include an if statement with a compound condition

Take this if:

let c = [1, 1, 1, 1]
// Doesn't work
if (abs(inputs.texCoord.x - 0.5) > 0.2 || abs(inputs.texCoord.y - 0.5) > 0.2) {
  c = [1, 0, 0, 1]
}

If I put a debugger statement in there, it's getting transpiled to this:

let c = __p5.strandsNode([
    1,
    1,
    1,
    1
])
{
    c = __p5.strandsNode(c)
    const __block_2 = __p5.strandsIf(abs(inputs.texCoord.x.sub(0.5)).greaterThan(0.2) || abs(inputs.texCoord.y.sub(0.5)).greaterThan(0.2), () => {
        let __copy_c_0 = c.copy()
        __copy_c_0 = __p5.strandsNode([
            1,
            0,
            0,
            1
        ])
        return { c: __copy_c_0 }
    }).Else(() => {
        let __copy_c_1 = c.copy()
        return { c: __copy_c_1 }
    })
    c = __block_2.c
}

Note that there's still an ||, which doesn't work because these are not actual booleans. It should be getting transpiled to a .or(...).

I thought this bit of the transpiler code would do that, but apparently it's not:

BinaryExpression(node, _state, ancestors) {
// Don't convert uniform default values to node methods, as
// they should be evaluated at runtime, not compiled.
if (ancestors.some(nodeIsUniform)) { return; }
// If the left hand side of an expression is one of these types,
// we should construct a node from it.
const unsafeTypes = ['Literal', 'ArrayExpression', 'Identifier'];
if (unsafeTypes.includes(node.left.type)) {
const leftReplacementNode = {
type: 'CallExpression',
callee: {
type: 'Identifier',
name: '__p5.strandsNode',
},
arguments: [node.left]
}
node.left = leftReplacementNode;
}
// Replace the binary operator with a call expression
// in other words a call to BaseNode.mult(), .div() etc.
node.type = 'CallExpression';
node.callee = {
type: 'MemberExpression',
object: node.left,
property: {
type: 'Identifier',
name: replaceBinaryOperator(node.operator),
},
};
node.arguments = [node.right];
},

Snippet:

Live: https://editor.p5js.org/davepagurek/sketches/5MtHbKB-A

let sh
async function setup() {
  createCanvas(windowWidth, windowHeight, WEBGL)
  sh = baseFilterShader().modify(() => {
    getColor((inputs) => {
      let c = [1, 1, 1, 1]
      // Doesn't work
      if (abs(inputs.texCoord.x - 0.5) > 0.2 || abs(inputs.texCoord.y - 0.5) > 0.2) {
        c = [1, 0, 0, 1]
      }
      
      // Works
      // if (abs(inputs.texCoord.x - 0.5) > 0.2 ) {
      //   c = [1, 0, 0, 1]
      // }
      // if (abs(inputs.texCoord.y - 0.5) > 0.2 ) {
      //   c = [1, 0, 0, 1]
      // }
      
      return c
    })
  })
}

function draw() {
  filter(sh)
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions