Skip to content

Commit 9512db6

Browse files
authored
Merge pull request #8359 from Aayushdev18/dev-2.0
Fix LogicalExpression (&&, ||) handling in p5.strands
2 parents 7fa997e + 88e5a23 commit 9512db6

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

src/strands/strands_transpiler.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,37 @@ const ASTCallbacks = {
275275
};
276276
node.arguments = [node.right];
277277
},
278+
LogicalExpression(node, _state, ancestors) {
279+
// Don't convert uniform default values to node methods, as
280+
// they should be evaluated at runtime, not compiled.
281+
if (ancestors.some(nodeIsUniform)) { return; }
282+
// If the left hand side of an expression is one of these types,
283+
// we should construct a node from it.
284+
const unsafeTypes = ['Literal', 'ArrayExpression', 'Identifier'];
285+
if (unsafeTypes.includes(node.left.type)) {
286+
const leftReplacementNode = {
287+
type: 'CallExpression',
288+
callee: {
289+
type: 'Identifier',
290+
name: '__p5.strandsNode',
291+
},
292+
arguments: [node.left]
293+
}
294+
node.left = leftReplacementNode;
295+
}
296+
// Replace the logical operator with a call expression
297+
// in other words a call to BaseNode.or(), .and() etc.
298+
node.type = 'CallExpression';
299+
node.callee = {
300+
type: 'MemberExpression',
301+
object: node.left,
302+
property: {
303+
type: 'Identifier',
304+
name: replaceBinaryOperator(node.operator),
305+
},
306+
};
307+
node.arguments = [node.right];
308+
},
278309
IfStatement(node, _state, ancestors) {
279310
if (ancestors.some(nodeIsUniform)) { return; }
280311
// Transform if statement into strandsIf() call

test/unit/webgl/p5.Shader.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,66 @@ suite('p5.Shader', function() {
714714
assert.approximately(pixelColor[1], 255, 5); // Green channel should be 255
715715
assert.approximately(pixelColor[2], 255, 5); // Blue channel should be 255
716716
});
717+
test('handle if statement with || (OR) operator', () => {
718+
myp5.createCanvas(50, 50, myp5.WEBGL);
719+
const testShader = myp5.baseMaterialShader().modify(() => {
720+
myp5.getPixelInputs(inputs => {
721+
let c = [1, 1, 1, 1];
722+
if (myp5.abs(inputs.texCoord.x - 0.5) > 0.2 || myp5.abs(inputs.texCoord.y - 0.5) > 0.2) {
723+
c = [1, 0, 0, 1];
724+
}
725+
inputs.color = c;
726+
return inputs;
727+
});
728+
}, { myp5 });
729+
myp5.noStroke();
730+
myp5.shader(testShader);
731+
myp5.plane(myp5.width, myp5.height);
732+
const centerPixel = myp5.get(25, 25);
733+
assert.approximately(centerPixel[0], 255, 5);
734+
assert.approximately(centerPixel[1], 255, 5);
735+
assert.approximately(centerPixel[2], 255, 5);
736+
const leftEdgePixel = myp5.get(5, 25);
737+
assert.approximately(leftEdgePixel[0], 255, 5);
738+
assert.approximately(leftEdgePixel[1], 0, 5);
739+
assert.approximately(leftEdgePixel[2], 0, 5);
740+
const topEdgePixel = myp5.get(25, 5);
741+
assert.approximately(topEdgePixel[0], 255, 5);
742+
assert.approximately(topEdgePixel[1], 0, 5);
743+
assert.approximately(topEdgePixel[2], 0, 5);
744+
});
745+
test('handle if statement with && (AND) operator', () => {
746+
myp5.createCanvas(50, 50, myp5.WEBGL);
747+
const testShader = myp5.baseMaterialShader().modify(() => {
748+
myp5.getPixelInputs(inputs => {
749+
let color = myp5.float(0.0);
750+
if (inputs.texCoord.x > 0.5 && inputs.texCoord.y > 0.5) {
751+
color = myp5.float(1.0);
752+
}
753+
inputs.color = [color, color, color, 1.0];
754+
return inputs;
755+
});
756+
}, { myp5 });
757+
myp5.noStroke();
758+
myp5.shader(testShader);
759+
myp5.plane(myp5.width, myp5.height);
760+
const bottomRightPixel = myp5.get(45, 45);
761+
assert.approximately(bottomRightPixel[0], 255, 5);
762+
assert.approximately(bottomRightPixel[1], 255, 5);
763+
assert.approximately(bottomRightPixel[2], 255, 5);
764+
const topLeftPixel = myp5.get(5, 5);
765+
assert.approximately(topLeftPixel[0], 0, 5);
766+
assert.approximately(topLeftPixel[1], 0, 5);
767+
assert.approximately(topLeftPixel[2], 0, 5);
768+
const topRightPixel = myp5.get(45, 5);
769+
assert.approximately(topRightPixel[0], 0, 5);
770+
assert.approximately(topRightPixel[1], 0, 5);
771+
assert.approximately(topRightPixel[2], 0, 5);
772+
const bottomLeftPixel = myp5.get(5, 45);
773+
assert.approximately(bottomLeftPixel[0], 0, 5);
774+
assert.approximately(bottomLeftPixel[1], 0, 5);
775+
assert.approximately(bottomLeftPixel[2], 0, 5);
776+
});
717777
// Keep one direct API test for completeness
718778
test('handle direct StrandsIf API usage', () => {
719779
myp5.createCanvas(50, 50, myp5.WEBGL);

0 commit comments

Comments
 (0)