Files
bitfielder/src/components/HelpPopup.tsx

321 lines
9.0 KiB
TypeScript

import React from 'react';
import { useStore } from '@nanostores/react';
import { uiState, hideHelp } from '../stores/ui';
export function HelpPopup() {
const ui = useStore(uiState);
const handleBackdropClick = (e: React.MouseEvent) => {
if (e.target === e.currentTarget) {
hideHelp();
}
};
if (!ui.helpPopupOpen) return null;
return (
<div
id="help-popup"
style={{ display: 'block' }}
onClick={handleBackdropClick}
>
<button className="close-btn" onClick={hideHelp}>
&times;
</button>
<h3>Bitfielder Help</h3>
<div className="help-content">
<div className="help-section">
<h4>Keyboard Shortcuts</h4>
<p>
<strong>Ctrl+Enter</strong> - Execute shader code
</p>
<p>
<strong>F11</strong> - Toggle fullscreen
</p>
<p>
<strong>H</strong> - Hide/show UI
</p>
<p>
<strong>R</strong> - Generate random shader
</p>
<p>
<strong>S</strong> - Share current shader (copy URL)
</p>
<p>
<strong>?</strong> - Show this help
</p>
</div>
<div className="help-section">
<h4>Variables</h4>
<p>
<strong>x, y</strong> - Pixel coordinates
</p>
<p>
<strong>t</strong> - Time (enables animation)
</p>
<p>
<strong>i</strong> - Pixel index
</p>
<p>
<strong>r</strong> - Distance from center
</p>
<p>
<strong>a</strong> - Angle from center (radians)
</p>
<p>
<strong>u, v</strong> - Normalized coordinates (0.0 to 1.0)
</p>
<p>
<strong>c</strong> - Normalized center distance (0.0 to 1.0)
</p>
<p>
<strong>f</strong> - Frame count (discrete timing)
</p>
<p>
<strong>d</strong> - Manhattan distance from center
</p>
<p>
<strong>n</strong> - Noise value (0.0 to 1.0)
</p>
<p>
<strong>b</strong> - Previous frame's value (feedback)
</p>
<p>
<strong>mouseX, mouseY</strong> - Mouse position (0.0 to 1.0)
</p>
<p>
<strong>mousePressed</strong> - Mouse button down (true/false)
</p>
<p>
<strong>mouseVX, mouseVY</strong> - Mouse velocity
</p>
<p>
<strong>mouseClickTime</strong> - Time since last click (ms)
</p>
</div>
<div className="help-section">
<h4>Touch & Gestures</h4>
<p>
<strong>touchCount</strong> - Number of active touches
</p>
<p>
<strong>touch0X, touch0Y</strong> - Primary touch position
</p>
<p>
<strong>touch1X, touch1Y</strong> - Secondary touch position
</p>
<p>
<strong>pinchScale</strong> - Pinch zoom scale factor
</p>
<p>
<strong>pinchRotation</strong> - Pinch rotation angle
</p>
</div>
<div className="help-section">
<h4>Device Motion</h4>
<p>
<strong>accelX, accelY, accelZ</strong> - Accelerometer data
</p>
<p>
<strong>gyroX, gyroY, gyroZ</strong> - Gyroscope rotation rates
</p>
</div>
<div className="help-section">
<h4>Audio Reactive</h4>
<p>
<strong>audioLevel</strong> - Overall audio volume (0.0-1.0)
</p>
<p>
<strong>bassLevel</strong> - Low frequencies (0.0-1.0)
</p>
<p>
<strong>midLevel</strong> - Mid frequencies (0.0-1.0)
</p>
<p>
<strong>trebleLevel</strong> - High frequencies (0.0-1.0)
</p>
<p>Click "Enable Audio" to activate microphone</p>
</div>
<div className="help-section">
<h4>Operators</h4>
<p>
<strong>^ & |</strong> - XOR, AND, OR
</p>
<p>
<strong>&lt;&lt; &gt;&gt;</strong> - Bit shift left/right
</p>
<p>
<strong>+ - * / %</strong> - Math operations
</p>
<p>
<strong>== != &lt; &gt;</strong> - Comparisons (return 0/1)
</p>
<p>
<strong>? :</strong> - Ternary operator (condition ? true : false)
</p>
<p>
<strong>~ **</strong> - Bitwise NOT, exponentiation
</p>
</div>
<div className="help-section">
<h4>Math Functions</h4>
<p>
<strong>sin, cos, tan</strong> - Trigonometric functions
</p>
<p>
<strong>abs, sqrt, pow</strong> - Absolute, square root, power
</p>
<p>
<strong>floor, ceil, round</strong> - Rounding functions
</p>
<p>
<strong>min, max</strong> - Minimum and maximum
</p>
<p>
<strong>random</strong> - Random number 0-1
</p>
<p>
<strong>log, exp</strong> - Natural logarithm, exponential
</p>
<p>
<strong>PI, E</strong> - Math constants
</p>
<p>
Use without Math. prefix: <code>sin(x)</code> not{' '}
<code>Math.sin(x)</code>
</p>
</div>
<div className="help-section">
<h4>Value Modes</h4>
<p>
<strong>Integer (0-255):</strong> Traditional mode for large values
</p>
<p>
<strong>Float (0.0-1.0):</strong> Bitfield shader mode, inverts and
clamps values
</p>
<p>
<strong>Polar (angle-based):</strong> Spiral patterns combining
angle and radius
</p>
<p>
<strong>Distance (radial):</strong> Concentric wave rings with
variable frequency
</p>
<p>
<strong>Wave (ripple):</strong> Multi-source interference with
amplitude falloff
</p>
<p>Each mode transforms your expression differently!</p>
</div>
<div className="help-section">
<h4>Advanced Features</h4>
<p>
<strong>Array indexing:</strong> <code>[1,2,4,8][floor(t%4)]</code>
</p>
<p>
<strong>Complex expressions:</strong>{' '}
<code>x&gt;y ? sin(x) : cos(y)</code>
</p>
<p>
<strong>Nested functions:</strong>{' '}
<code>pow(sin(x), abs(y-x))</code>
</p>
<p>
<strong>Logical operators:</strong> <code>x&amp;&amp;y</code>,{' '}
<code>x||y</code>
</p>
<p>No character or length limits - use any JavaScript!</p>
</div>
<div className="help-section">
<h4>Shader Library</h4>
<p>
Hover over the <strong>left edge</strong> of the screen to access
the shader library
</p>
<p>Save shaders with custom names and search through them</p>
<p>
Use <strong>edit</strong> to rename, <strong>del</strong> to delete
</p>
</div>
<div className="help-section">
<h4>Render Modes</h4>
<p>
<strong>Classic</strong> - Original colorful mode
</p>
<p>
<strong>Grayscale</strong> - Black and white
</p>
<p>
<strong>Red/Green/Blue</strong> - Single color channels
</p>
<p>
<strong>HSV</strong> - Hue-based coloring
</p>
<p>
<strong>Rainbow</strong> - Spectrum coloring
</p>
</div>
<div className="help-section">
<h4>Export</h4>
<p>
<strong>Export PNG</strong> - Save current frame as image
</p>
</div>
</div>
<div
className="help-section"
style={{
gridColumn: '1 / -1',
marginTop: '20px',
textAlign: 'center',
paddingTop: '20px',
borderBottom: 'none',
}}
>
<h4>About</h4>
<p>
<strong>Bitfielder</strong> - Interactive bitfield shader editor
</p>
<p>
Created by <strong>BuboBubo</strong> (Raphaël Forment)
</p>
<p>
Website:{' '}
<a
href="https://raphaelforment.fr"
target="_blank"
>
raphaelforment.fr
</a>
</p>
<p>
Source:{' '}
<a
href="https://git.raphaelforment.fr"
target="_blank"
>
git.raphaelforment.fr
</a>
</p>
<p>
License: <strong>AGPL 3.0</strong>
</p>
</div>
</div>
);
}