Skip to content

Commit 7f7bf73

Browse files
committed
Combine X/Y node parameters into one section in the inspector
1 parent c055ded commit 7f7bf73

File tree

12 files changed

+129
-161
lines changed

12 files changed

+129
-161
lines changed

packages/material/node-parameter.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export type ParameterInputType = "number" | "rgb" | "select";
2-
export type ParameterValueType = "int" | "float" | "vec3";
2+
export type ParameterValueType = "int" | "float" | "vec2" | "vec3" | "ivec2";
33

44
type MakeParameterInputInfo<
55
InputType extends ParameterInputType,
@@ -23,8 +23,8 @@ type MakeParameterInputInfo<
2323
export type NumberParameterInputInfo = MakeParameterInputInfo<
2424
"number",
2525
{ min: number; max: number; step?: number },
26-
number,
27-
"int" | "float"
26+
number | Array<number>,
27+
"int" | "float" | "vec2" | "vec3" | "ivec2"
2828
>;
2929

3030
export type RgbParameterInputInfo = MakeParameterInputInfo<

packages/renderer/webgl2/painters/scatter.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ export default class ScatterNodePainter extends PatternNodePainter {
99

1010
const randomnessSeed = node.parameters["seed"] as number;
1111
const size = (node.parameters["size"] as number) * 2048;
12-
const spreadX = node.parameters["spreadX"] as number;
13-
const spreadY = node.parameters["spreadY"] as number;
12+
const spread = node.parameters["spread"] as [number, number];
1413
const randomRotation = node.parameters["randomRotation"] as number;
1514
const randomScale = (node.parameters["randomScale"] as number) / 2048;
1615

@@ -22,7 +21,7 @@ export default class ScatterNodePainter extends PatternNodePainter {
2221
const scale = size / 2048 + rng() * randomScale - randomScale / 2;
2322
elements.push({
2423
rotation: rng() * randomRotation,
25-
position: [rng() * spreadX - spreadX / 2, rng() * spreadY - spreadY / 2, 0],
24+
position: [rng() * spread[0] - spread[0] / 2, rng() * spread[1] - spread[1] / 2, 0],
2625
scale: [scale, scale],
2726
});
2827
}

packages/renderer/webgl2/painters/tile.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ export default class TileNodePainter extends PatternNodePainter {
66
const node = snapshot.node;
77
const elements: Array<PatternElement> = [];
88

9-
const amountX = Math.floor(node.parameters["amountX"] as number);
10-
const amountY = Math.floor(node.parameters["amountY"] as number);
11-
const extraOffsetX = (node.parameters["offsetX"] as number) / amountX;
12-
const extraOffsetY = (node.parameters["offsetY"] as number) / amountY;
9+
const amountXY = node.parameters["amount"] as [number, number];
10+
const amountX = Math.floor(amountXY[0]);
11+
const amountY = Math.floor(amountXY[1]);
12+
const extraOffsetXY = node.parameters["offset"] as [number, number];
13+
const extraOffsetX = extraOffsetXY[0] / amountX;
14+
const extraOffsetY = extraOffsetXY[1] / amountY;
1315
const scale = 1 / Math.max(amountX, amountY);
1416

1517
const toAddY = Math.ceil(extraOffsetY * amountY * amountY + 1);
Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,86 @@
1-
import { createEffect, createSignal } from "solid-js";
1+
import { Accessor, For, createEffect, createSignal } from "solid-js";
22
import { NumberParameterInputInfo } from "../../../../material/node-parameter";
33
import HorizontalSlider from "../../../components/slider/horizontalSlider";
44
import { InputProps } from "../parameter";
55

66
export default function MaterialNodeInspectorNumberInput(
7-
props: InputProps<NumberParameterInputInfo, number>,
7+
props: InputProps<NumberParameterInputInfo, number | Array<number>>,
88
) {
9-
const [maxScale, setMaxScale] = createSignal(1);
10-
const isFloat = props.parameter.valueType === "float";
9+
const isFloat = props.parameter.valueType !== "int" && props.parameter.valueType !== "ivec2";
1110

12-
createEffect(() => {
13-
const max = props.parameter.inputProps.max ?? 1;
14-
if (props.value() > max * maxScale()) {
15-
setMaxScale((s) => s * 2);
16-
}
17-
});
11+
function onChange(index: number, value: number) {
12+
const currentValue = props.value() as Array<number>;
13+
const newValue = [...currentValue];
14+
newValue[index] = value;
15+
props.onChange(newValue);
16+
}
17+
18+
function InnerInput({
19+
value,
20+
onChange,
21+
}: {
22+
value: Accessor<number>;
23+
onChange: (value: number) => void;
24+
}) {
25+
const [maxScale, setMaxScale] = createSignal(1);
26+
27+
createEffect(() => {
28+
const max = props.parameter.inputProps.max ?? 1;
29+
if (value() > max * maxScale()) {
30+
setMaxScale((s) => s * 2);
31+
}
32+
});
33+
34+
return (
35+
<div class="flex items-center gap-4">
36+
<input
37+
style={{ width: "44px" }}
38+
class="hide-spin-button py-0.5 outline-none bg-gray-0 border border-gray-200 text-xs text-center rounded-md"
39+
type="number"
40+
value={isFloat ? value().toFixed(2) : value()}
41+
onChange={(ev) =>
42+
onChange(isFloat ? parseFloat(ev.target.value) : parseInt(ev.target.value))
43+
}
44+
/>
45+
46+
<HorizontalSlider
47+
min={props.parameter.inputProps.min ?? 0}
48+
max={(props.parameter.inputProps.max ?? 1) * maxScale()}
49+
step={props.parameter.inputProps.step ?? 0.01}
50+
value={value()}
51+
onChange={(value) => onChange(isFloat ? value : Math.round(value))}
52+
onPointerDown={props.onFocus}
53+
onPointerUp={props.onBlur}
54+
/>
55+
</div>
56+
);
57+
}
58+
59+
const numberOfInputs = getNumberOfInputs(props.parameter);
60+
if (numberOfInputs === 1) {
61+
return <InnerInput value={() => props.value() as number} onChange={props.onChange} />;
62+
}
1863

1964
return (
20-
<div class="flex items-center gap-4">
21-
<input
22-
style={{ width: "44px" }}
23-
class="hide-spin-button py-0.5 outline-none bg-gray-0 border border-gray-200 text-xs text-center rounded-md"
24-
type="number"
25-
value={isFloat ? props.value().toFixed(2) : props.value()}
26-
onChange={(ev) =>
27-
props.onChange(
28-
isFloat ? parseFloat(ev.target.value) : parseInt(ev.target.value),
29-
)
30-
}
31-
/>
32-
33-
<HorizontalSlider
34-
min={props.parameter.inputProps.min ?? 0}
35-
max={(props.parameter.inputProps.max ?? 1) * maxScale()}
36-
step={props.parameter.inputProps.step ?? 0.01}
37-
value={props.value()}
38-
onChange={(value) => props.onChange(isFloat ? value : Math.round(value))}
39-
onPointerDown={props.onFocus}
40-
onPointerUp={props.onBlur}
41-
/>
65+
<div class="flex flex-col gap-2">
66+
<For each={Array(numberOfInputs).fill(0)}>
67+
{(_, index) => (
68+
<InnerInput
69+
value={() => (props.value() as Array<number>)[index()]}
70+
onChange={(v) => onChange(index(), v)}
71+
/>
72+
)}
73+
</For>
4274
</div>
4375
);
4476
}
77+
78+
function getNumberOfInputs(parameter: NumberParameterInputInfo) {
79+
if (parameter.valueType === "vec2" || parameter.valueType === "ivec2") {
80+
return 2;
81+
} else if (parameter.valueType === "vec3") {
82+
return 3;
83+
}
84+
85+
return 1;
86+
}

resources/nodes/layout/scatter.ts

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,12 @@ export default {
2828
max: 1,
2929
},
3030
},
31-
spreadX: {
32-
id: "spreadX",
33-
name: "Spread X",
34-
default: 1,
35-
inputType: "number",
36-
valueType: "float",
37-
inputProps: {
38-
min: 0,
39-
max: 4,
40-
},
41-
},
42-
spreadY: {
43-
id: "spreadY",
44-
name: "Spread Y",
45-
default: 1,
31+
spread: {
32+
id: "spread",
33+
name: "Spread X/Y",
34+
default: [1, 1],
4635
inputType: "number",
47-
valueType: "float",
36+
valueType: "vec2",
4837
inputProps: {
4938
min: 0,
5039
max: 4,

resources/nodes/layout/tile.ts

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,23 @@ export default {
55
name: "Tile",
66
groupName: "Layout",
77
parameters: {
8-
amountX: {
9-
id: "amountX",
10-
name: "Amount X",
11-
default: 1,
8+
amount: {
9+
id: "amount",
10+
name: "Amount X/Y",
11+
default: [1, 1],
1212
inputType: "number",
13-
valueType: "int",
13+
valueType: "ivec2",
1414
inputProps: {
1515
min: 1,
1616
max: 16,
1717
},
1818
},
19-
amountY: {
20-
id: "amountY",
21-
name: "Amount Y",
22-
default: 1,
19+
offset: {
20+
id: "offset",
21+
name: "Offset X/Y",
22+
default: [0, 0],
2323
inputType: "number",
24-
valueType: "int",
25-
inputProps: {
26-
min: 1,
27-
max: 16,
28-
},
29-
},
30-
offsetX: {
31-
id: "offsetX",
32-
name: "Offset X",
33-
default: 0,
34-
inputType: "number",
35-
valueType: "float",
36-
inputProps: {
37-
min: 0,
38-
max: 1,
39-
},
40-
},
41-
offsetY: {
42-
id: "offsetY",
43-
name: "Offset Y",
44-
default: 0,
45-
inputType: "number",
46-
valueType: "float",
24+
valueType: "vec2",
4725
inputProps: {
4826
min: 0,
4927
max: 1,

resources/nodes/layout/transform.glsl

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ precision highp float;
33

44
in vec2 a_texCoord;
55

6-
uniform float p_offsetX;
7-
uniform float p_offsetY;
6+
uniform vec2 p_offset;
87
uniform float p_rotation;
9-
uniform float p_scaleX;
10-
uniform float p_scaleY;
8+
uniform vec2 p_scale;
119
uniform int p_wrapMode;
1210

1311
uniform sampler2D i_in;
@@ -19,7 +17,7 @@ out vec4 out_color;
1917
#define WRAP_MODE_CUTOUT 2
2018

2119
vec2 translateUV(vec2 uv, vec2 translation) {
22-
return vec2(mod(uv.x + p_offsetX, 1.0f), mod(uv.y + p_offsetY, 1.0f));
20+
return vec2(mod(uv.x + p_offset.x, 1.0f), mod(uv.y + p_offset.y, 1.0f));
2321
}
2422

2523
vec2 rotateUV(vec2 uv, float rotation, vec2 pivot) {
@@ -32,9 +30,9 @@ vec2 scaleUV(vec2 uv, vec2 scale, vec2 pivot) {
3230

3331
void main(void) {
3432
vec2 uv = vec2(0.0f);
35-
uv = translateUV(a_texCoord, vec2(p_offsetX, p_offsetY));
33+
uv = translateUV(a_texCoord, vec2(p_offset.x, p_offset.y));
3634
uv = rotateUV(uv, radians(360.0f - p_rotation), vec2(0.5f, 0.5f));
37-
uv = scaleUV(uv, vec2(p_scaleX, p_scaleY), vec2(0.5f, 0.5f));
35+
uv = scaleUV(uv, vec2(p_scale.x, p_scale.y), vec2(0.5f, 0.5f));
3836

3937
if(p_wrapMode == WRAP_MODE_REPEAT) {
4038
uv.x = mod(uv.x, 1.0f);

resources/nodes/layout/transform.ts

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,16 @@ export default {
66
name: "Transform",
77
groupName: "Layout",
88
parameters: {
9-
offsetX: {
10-
id: "offsetX",
11-
name: "Offset X",
12-
default: 0,
13-
inputType: "number",
14-
inputProps: {
15-
min: -1,
16-
max: 1,
17-
},
18-
valueType: "float",
19-
},
20-
offsetY: {
21-
id: "offsetY",
22-
name: "Offset Y",
23-
default: 0,
9+
offset: {
10+
id: "offset",
11+
name: "Offset X/Y",
12+
default: [0, 0],
2413
inputType: "number",
2514
inputProps: {
2615
min: -1,
2716
max: 1,
2817
},
29-
valueType: "float",
18+
valueType: "vec2",
3019
},
3120
rotation: {
3221
id: "rotation",
@@ -39,27 +28,16 @@ export default {
3928
},
4029
valueType: "float",
4130
},
42-
scaleX: {
43-
id: "scaleX",
44-
name: "Scale X",
45-
default: 1,
31+
scale: {
32+
id: "scale",
33+
name: "Scale X/Y",
34+
default: [1, 1],
4635
inputType: "number",
4736
inputProps: {
4837
min: 0,
4938
max: 2,
5039
},
51-
valueType: "float",
52-
},
53-
scaleY: {
54-
id: "scaleY",
55-
name: "Scale Y",
56-
default: 1,
57-
inputType: "number",
58-
inputProps: {
59-
min: 0,
60-
max: 2,
61-
},
62-
valueType: "float",
40+
valueType: "vec2",
6341
},
6442
wrapMode: {
6543
id: "wrapMode",

resources/nodes/noises/perlin.fs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ precision highp float;
33

44
in vec2 a_texCoord;
55

6-
uniform float p_offsetX;
7-
uniform float p_offsetY;
6+
uniform vec2 p_offset;
87
uniform float p_sharpness;
98
uniform float p_scale;
109
uniform int p_levels;
@@ -39,7 +38,7 @@ void main(void) {
3938
out_color = vec4(0, 0, 0, 1);
4039

4140
vec2 uv = a_texCoord;
42-
uv += vec2(p_offsetX, p_offsetY);
41+
uv += p_offset;
4342
uv *= p_scale;
4443

4544
float n = 0.0f;

0 commit comments

Comments
 (0)