321 lines
9.0 KiB
TypeScript
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}>
|
|
×
|
|
</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><< >></strong> - Bit shift left/right
|
|
</p>
|
|
<p>
|
|
<strong>+ - * / %</strong> - Math operations
|
|
</p>
|
|
<p>
|
|
<strong>== != < ></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>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&&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>
|
|
);
|
|
}
|