diff --git a/swizzle-generator.js b/swizzle-generator.js index 6db02d7be..969272b70 100644 --- a/swizzle-generator.js +++ b/swizzle-generator.js @@ -18,6 +18,14 @@ for (let i = 0; i < 4; i++) { } } +let swizzleOptionsNoRepetitionContiguousOrdered = []; +for (let i = 0; i < 4; i++) { + swizzleOptionsNoRepetitionContiguousOrdered[i] = []; + for (let j = 0; j < 4; j++) { + swizzleOptionsNoRepetitionContiguousOrdered[i][j] = []; + } +} + let swizzleOptionsNoRepetitionOrdered = []; for (let i = 0; i < 4; i++) { swizzleOptionsNoRepetitionOrdered[i] = []; @@ -67,6 +75,16 @@ function setProtoSwizzle(a, b, c, d) { } } + if (b == null || a === b - 1) { + if (c == null || b === c - 1) { + if (d == null || c === d - 1) { + swizzleOptionsNoRepetitionContiguousOrdered[numChars - 1][maxCharNum].push(prop); + swizzleOptionsNoRepetitionContiguousOrdered[numChars - 1][maxCharNum].push(altA); + swizzleOptionsNoRepetitionContiguousOrdered[numChars - 1][maxCharNum].push(altB); + } + } + } + if (b == null || a < b) { if (c == null || a < c && b < c) { if (d == null || c < d && b < d && a < d) { @@ -128,7 +146,7 @@ for (let i = 0; i < 4; i++) { console.log(`interface SetSwizzle${i + 1} {`); for (let j = 0; j <= i; j++) { for (let k = 0; k <= i; k++) { - const arr = swizzleOptionsNoRepetitionOrdered[j][k]; + const arr = swizzleOptionsNoRepetitionContiguousOrdered[j][k]; for (const val of arr) { console.log(` set${val.toUpperCase()}(value: ${assignType[j]}): ${accessType[i]};`); } diff --git a/tsl-testing/TSLCore.ts b/tsl-testing/TSLCore.ts index b9045bb48..1e14b7c24 100644 --- a/tsl-testing/TSLCore.ts +++ b/tsl-testing/TSLCore.ts @@ -53,7 +53,8 @@ testVec3.setXY(5); // Allow passing a vec of the right size when setting a vec swizzle property testVec3.setXY(testVec2); -// Allow elements that are not right next to each other +// Disallow elements that are not right next to each other, they are not handled properly +// @ts-expect-error testVec3.setXZ(3); // vec2s don't have a z property @@ -64,6 +65,10 @@ testVec2.setXZ(testVec2); // @ts-expect-error testVec3.setXY(testVec3); +// Disallow elements that are not right next to each other, they are not handled properly +// @ts-expect-error +testVec3.setXZ(testVec2); + // Disallow duplicate identifiers when setting a vec swizzle property // @ts-expect-error testVec3.setXX(5); @@ -87,7 +92,8 @@ testVec3.flipXZ(); // @ts-expect-error testVec2.flipXZ(); -// Disallow out-of-order identifiers, since they are sorted internally +// Disallow out-of-order identifiers. They are functionally identically to the sorted variant, and unnecessarily add to +// the number of available methods // @ts-expect-error testVec3.flipZX(); diff --git a/tsl-testing/node-type.test.ts b/tsl-testing/node-type.test.ts index 3c5588891..64cd26c74 100644 --- a/tsl-testing/node-type.test.ts +++ b/tsl-testing/node-type.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest"; -import { Fn, normalWorldGeometry, vec2, vec3 } from "three/tsl"; +import { Fn, normalWorldGeometry, vec2, vec3, vec4 } from "three/tsl"; import * as THREE from "three/webgpu"; const renderer = new THREE.WebGPURenderer(); @@ -112,6 +112,23 @@ test("vec3(1, 0, 2).xz = 6", async () => { renderer.render(scene, camera); }); +test("vec3(1, 0, 2).xz = vec2(2, 3)", async () => { + const fn = Fn(() => { + const testVec3 = vec3(1, 0, 2); + testVec3.xz = vec2(2, 3); + return testVec3; + }); + + const result: THREE.Node<"vec3"> = fn(); + + expect(result.getNodeType(nodeBuilder)).toBe("vec3"); + + scene.backgroundNode = result.debug(); + + await renderer.init(); + renderer.render(scene, camera); +}); + test("vec3(1, 0, 2).setXY(5)", async () => { const testVec3Set: THREE.Node<"vec3"> = vec3(1, 0, 2).setXY(5); @@ -123,7 +140,21 @@ test("vec3(1, 0, 2).setXY(5)", async () => { renderer.render(scene, camera); }); +test("vec4(1, 0, 2, 5).setYZ(vec2(5, 3))", async () => { + const testVec3Set: THREE.Node<"vec4"> = vec4(1, 0, 2, 5).setYZ(vec2(5, 3)); + + expect(testVec3Set.getNodeType(nodeBuilder)).toBe("vec4"); + + scene.backgroundNode = testVec3Set.debug(); + + await renderer.init(); + renderer.render(scene, camera); +}); + test("vec3(1, 0, 2).setXZ(3)", async () => { + // This doesn't work as expected, the resulting output is: + // vec3( vec2( 3.0 ), vec3( 1.0, 0.0, 2.0 ).z ) + // @ts-expect-error const testVec3Set: THREE.Node<"vec3"> = vec3(1, 0, 2).setXZ(3); expect(testVec3Set.getNodeType(nodeBuilder)).toBe("vec3"); @@ -134,6 +165,20 @@ test("vec3(1, 0, 2).setXZ(3)", async () => { renderer.render(scene, camera); }); +test("vec3(1, 0, 2).setXZ(vec2(5, 3))", async () => { + // This doesn't work as expected, the resulting output is: + // vec3( vec2( 5.0, 3.0 ), vec3( 1.0, 0.0, 2.0 ).z ) + // @ts-expect-error + const testVec3Set: THREE.Node<"vec3"> = vec3(1, 0, 2).setXZ(vec2(5, 3)); + + expect(testVec3Set.getNodeType(nodeBuilder)).toBe("vec3"); + + scene.backgroundNode = testVec3Set.debug(); + + await renderer.init(); + renderer.render(scene, camera); +}); + test("vec3(1, 0, 2).setYZ(3)", async () => { const testVec3Set: THREE.Node<"vec3"> = vec3(1, 0, 2).setYZ(3); @@ -179,6 +224,7 @@ test("vec3(1, 0, 2).flipXZ()", async () => { }); test("vec3(1, 0, 2).flipZX()", async () => { + // This is functions correctly, but we don't include it to cut down on the number of methods // @ts-expect-error const testVec3Set: THREE.Node<"vec3"> = vec3(1, 0, 2).flipZX(); diff --git a/types/three/src/nodes/tsl/TSLCore.d.ts b/types/three/src/nodes/tsl/TSLCore.d.ts index dcc649c0e..75e868d58 100644 --- a/types/three/src/nodes/tsl/TSLCore.d.ts +++ b/types/three/src/nodes/tsl/TSLCore.d.ts @@ -1371,9 +1371,6 @@ interface SetSwizzle3 { setXY(value: Node> | NumOrBool): Node>; setRG(value: Node> | NumOrBool): Node>; setST(value: Node> | NumOrBool): Node>; - setXZ(value: Node> | NumOrBool): Node>; - setRB(value: Node> | NumOrBool): Node>; - setSP(value: Node> | NumOrBool): Node>; setYZ(value: Node> | NumOrBool): Node>; setGB(value: Node> | NumOrBool): Node>; setTP(value: Node> | NumOrBool): Node>; @@ -1398,30 +1395,15 @@ interface SetSwizzle4 { setXY(value: Node> | NumOrBool): Node>; setRG(value: Node> | NumOrBool): Node>; setST(value: Node> | NumOrBool): Node>; - setXZ(value: Node> | NumOrBool): Node>; - setRB(value: Node> | NumOrBool): Node>; - setSP(value: Node> | NumOrBool): Node>; setYZ(value: Node> | NumOrBool): Node>; setGB(value: Node> | NumOrBool): Node>; setTP(value: Node> | NumOrBool): Node>; - setXW(value: Node> | NumOrBool): Node>; - setRA(value: Node> | NumOrBool): Node>; - setSQ(value: Node> | NumOrBool): Node>; - setYW(value: Node> | NumOrBool): Node>; - setGA(value: Node> | NumOrBool): Node>; - setTQ(value: Node> | NumOrBool): Node>; setZW(value: Node> | NumOrBool): Node>; setBA(value: Node> | NumOrBool): Node>; setPQ(value: Node> | NumOrBool): Node>; setXYZ(value: Node> | NumOrBool): Node>; setRGB(value: Node> | NumOrBool): Node>; setSTP(value: Node> | NumOrBool): Node>; - setXYW(value: Node> | NumOrBool): Node>; - setRGA(value: Node> | NumOrBool): Node>; - setSTQ(value: Node> | NumOrBool): Node>; - setXZW(value: Node> | NumOrBool): Node>; - setRBA(value: Node> | NumOrBool): Node>; - setSPQ(value: Node> | NumOrBool): Node>; setYZW(value: Node> | NumOrBool): Node>; setGBA(value: Node> | NumOrBool): Node>; setTPQ(value: Node> | NumOrBool): Node>;