refactor: gen

This commit is contained in:
cha0s 2024-09-18 17:46:42 -05:00
parent 6a45622b9d
commit 749a3356c3
8 changed files with 241 additions and 12 deletions

View File

@ -61,6 +61,9 @@ module.exports = {
},
rules: {
'react/prop-types': 'off',
'jsx-a11y/label-has-associated-control': [2, {
controlComponents: ['SliderText'],
}],
},
},

View File

@ -0,0 +1,43 @@
import {useState} from 'react';
function SliderText({
defaultValue,
max,
min,
name,
onChange,
step,
}) {
const [value, setValue] = useState(defaultValue);
return (
<>
<input
value={value}
max={max}
min={min}
name={name}
onChange={({currentTarget: {value}}) => {
setValue(value);
if (onChange) {
onChange(value);
}
}}
step={step}
type="range"
/>
<input
value={value}
name={name}
onChange={({currentTarget: {value}}) => {
setValue(value);
if (onChange) {
onChange(value);
}
}}
type="text"
/>
</>
)
}
export default SliderText;

View File

@ -0,0 +1,10 @@
import styles from './layer.module.css';
function Layer() {
return (
<>
</>
);
}
export default Layer;

View File

@ -0,0 +1,51 @@
import SliderText from '@/react/components/dev/slider-text.jsx';
import styles from './noise-field.module.css';
function NoiseField(props) {
const {children, ...field} = props;
return (
<div className={styles.noiseField}>
<input
name="label[]"
type="text"
defaultValue={field.label}
/>
<label>
<SliderText
name="percent[]"
min="0"
max="1"
step="0.05"
defaultValue={field.percent}
/>
<span>%</span>
</label>
<div className={styles.scale}>
<label>
<span>x</span>
<SliderText
defaultValue={field.scale.x}
max="100"
min="0.01"
name="scaleX[]"
step="0.01"
/>
</label>
<label>
<span>y</span>
<SliderText
defaultValue={field.scale.y}
max="100"
min="0.01"
name="scaleY[]"
step="0.01"
/>
</label>
</div>
{children}
</div>
);
}
export default NoiseField;

View File

@ -0,0 +1,16 @@
.noiseField {
gap: 8px;
&, label {
align-items: center;
display: flex;
}
[type="text"][name^="label"] {
width: 10em;
}
[type="text"][name^="percent"] {
width: 3em;
}
[type="text"][name^="scale"] {
width: 4em;
}
}

View File

@ -0,0 +1,107 @@
// import {Container, Sprite, Stage} from '@pixi/react';
import {Form, json, redirect, useLoaderData} from '@remix-run/react';
import {useState} from 'react';
import {commitSession, getSession, juggleSession} from '@/server/session.server.js';
import NoiseField from './noise-field.jsx';
function getFormSession(session) {
return session.get('formSession') || {
fields: [],
};
}
export async function action({request}) {
const session = await getSession(request.headers.get('Cookie'));
const formSession = getFormSession(session);
const formData = await request.formData();
const op = formData.get('op');
if ('add-field' === op) {
formSession.fields.push({
label: '',
percent: 100,
scale: {x: 1, y: 1},
});
}
else if (op.startsWith('delete/')) {
const index = parseInt(op.slice('delete/'.length));
if (index >= 0 && index < formSession.fields.length) {
formSession.fields.splice(index, 1);
}
else {
throw new Error('delete out of bounds');
}
}
else if (op.startsWith('update/')) {
const index = parseInt(op.slice('update/'.length));
if (index >= 0 && index < formSession.fields.length) {
formSession.fields[index] = {
label: formData.getAll('label[]')[index],
percent: formData.getAll('percent[]')[index],
scale: {
x: formData.getAll('scaleX[]')[index],
y: formData.getAll('scaleY[]')[index],
},
}
}
else {
throw new Error('delete out of bounds');
}
}
else {
throw new Error('unknown operation');
}
session.set('formSession', formSession);
return json(null, {
headers: {
'Set-Cookie': await commitSession(session),
},
});
}
export async function loader({request}) {
const session = await juggleSession(request);
return json({
formSession: getFormSession(session),
});
}
function Gen() {
const {formSession: {fields}} = useLoaderData();
return (
<>
<Form
method="post"
>
{fields.map((field, i) => (
<NoiseField
key={i}
{...field}
>
<button
name="op"
value={['update', i].join('/')}
>
o
</button>
<button
name="op"
value={['delete', i].join('/')}
>
x
</button>
</NoiseField>
))}
<button
name="op"
value="add-field"
>
Add field
</button>
</Form>
</>
);
}
export default Gen;

View File

@ -1,6 +1,7 @@
import {Container, Sprite, Stage} from '@pixi/react';
import {useState} from 'react';
import SliderText from '@/react/components/dev/slider-text.jsx';
import TileLayer from '@/react/components/pixi/tile-layer.jsx';
import AssetsContext from '@/react/context/assets.js';
import {CHUNK_SIZE} from '@/util/constants.js';
@ -45,8 +46,8 @@ function Gen() {
const area = {x: 80, y: 80};
const assetsTuple = useState({});
const [seed, setSeed] = useState(0);
const [dirtClump, setDirtClump] = useState(30);
const [dirtPer, setDirtPer] = useState(0.3);
const [dirtClump, setDirtClump] = useState(60);
const [dirtPer, setDirtPer] = useState(0.6);
const dirtCheck = (x, y, noise) => noise(x / dirtClump, y / dirtClump) < dirtPer;
@ -163,21 +164,19 @@ function Gen() {
</AssetsContext.Provider>
</Stage>
<input type="text" onChange={({currentTarget: {value}}) => setSeed(value || 0)} value={seed} />
<input
type="range"
min="0"
<SliderText
max="1"
min="0"
onChange={(value) => setDirtPer(value)}
step="0.05"
value={dirtPer}
onChange={({currentTarget: {value}}) => setDirtPer(value)}
defaultValue={dirtPer}
/>
<input
type="range"
min="1"
<SliderText
max="100"
min="1"
onChange={(value) => setDirtClump(value)}
step="1"
value={dirtClump}
onChange={({currentTarget: {value}}) => setDirtClump(value)}
defaultValue={dirtClump}
/>
</>
);