This commit is contained in:
Flatlogic Bot 2026-03-27 23:49:05 +00:00
parent edc6d68e9e
commit 390f2b5058
3 changed files with 46 additions and 18 deletions

View File

@ -415,7 +415,7 @@ textarea::placeholder {
height: 142px; height: 142px;
border-radius: 30px; border-radius: 30px;
transform-origin: right bottom; transform-origin: right bottom;
transform: translateZ(66px) rotate(calc(-6deg + (var(--angle) * 0.38deg))); transform: translateZ(66px) rotate(calc(-6deg + (var(--angle) * 0.38deg) + (var(--back-angle) * 1deg)));
} }
.recliner-back-inner { .recliner-back-inner {
@ -428,7 +428,7 @@ textarea::placeholder {
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
transform-origin: right bottom; transform-origin: right bottom;
transform: translateZ(82px) rotate(calc(-6deg + (var(--angle) * 0.38deg))); transform: translateZ(82px) rotate(calc(-6deg + (var(--angle) * 0.38deg) + (var(--back-angle) * 1deg)));
} }
.recliner-head { .recliner-head {
@ -437,7 +437,8 @@ textarea::placeholder {
width: 74px; width: 74px;
height: 38px; height: 38px;
border-radius: 22px; border-radius: 22px;
transform: translateZ(86px) rotate(calc(-10deg + (var(--angle) * 0.14deg))); transform-origin: right bottom;
transform: translateZ(86px) rotate(calc(-10deg + (var(--angle) * 0.14deg) + (var(--head-angle) * 1deg)));
} }
.recliner-leg { .recliner-leg {
@ -447,7 +448,7 @@ textarea::placeholder {
height: 118px; height: 118px;
border-radius: 20px; border-radius: 20px;
transform-origin: left center; transform-origin: left center;
transform: translateZ(46px) rotate(calc(10deg + (var(--angle) * 0.34deg))); transform: translateZ(46px) rotate(calc(10deg + (var(--angle) * 0.34deg) + (var(--leg-angle) * 1deg)));
} }
.recliner-footpad { .recliner-footpad {
@ -457,7 +458,7 @@ textarea::placeholder {
height: 58px; height: 58px;
border-radius: 18px; border-radius: 18px;
transform-origin: left center; transform-origin: left center;
transform: translateZ(30px) rotate(calc(10deg + (var(--angle) * 0.2deg))); transform: translateZ(30px) rotate(calc(10deg + (var(--angle) * 0.2deg) + (var(--leg-angle) * 1deg)));
} }
.recliner-figure.is-vibrating .recliner-glow { .recliner-figure.is-vibrating .recliner-glow {

View File

@ -6,6 +6,9 @@ document.addEventListener('DOMContentLoaded', () => {
const controls = { const controls = {
angle: document.getElementById('angle_deg'), angle: document.getElementById('angle_deg'),
backAngle: document.getElementById('back_angle'),
legAngle: document.getElementById('leg_angle'),
headAngle: document.getElementById('head_angle'),
intensity: document.getElementById('intensity_pct'), intensity: document.getElementById('intensity_pct'),
pattern: document.getElementById('pattern_mode'), pattern: document.getElementById('pattern_mode'),
name: document.getElementById('name'), name: document.getElementById('name'),
@ -18,6 +21,9 @@ document.addEventListener('DOMContentLoaded', () => {
motionState: document.getElementById('motion-state'), motionState: document.getElementById('motion-state'),
angleValue: document.getElementById('angle-value'), angleValue: document.getElementById('angle-value'),
anglePill: document.getElementById('angle-pill'), anglePill: document.getElementById('angle-pill'),
backAnglePill: document.getElementById('back-angle-pill'),
legAnglePill: document.getElementById('leg-angle-pill'),
headAnglePill: document.getElementById('head-angle-pill'),
intensityPill: document.getElementById('intensity-pill'), intensityPill: document.getElementById('intensity-pill'),
statAngle: document.getElementById('stat-angle'), statAngle: document.getElementById('stat-angle'),
statIntensity: document.getElementById('stat-intensity'), statIntensity: document.getElementById('stat-intensity'),
@ -63,6 +69,9 @@ document.addEventListener('DOMContentLoaded', () => {
const currentState = () => ({ const currentState = () => ({
angle: Number(controls.angle?.value || 0), angle: Number(controls.angle?.value || 0),
backAngle: Number(controls.backAngle?.value || 0),
legAngle: Number(controls.legAngle?.value || 0),
headAngle: Number(controls.headAngle?.value || 0),
intensity: Number(controls.intensity?.value || 0), intensity: Number(controls.intensity?.value || 0),
pattern: controls.pattern?.value || 'continuous' pattern: controls.pattern?.value || 'continuous'
}); });
@ -95,6 +104,9 @@ document.addEventListener('DOMContentLoaded', () => {
const glowOpacity = Math.min(0.92, 0.36 + state.intensity / 180).toFixed(2); const glowOpacity = Math.min(0.92, 0.36 + state.intensity / 180).toFixed(2);
ui.figure.style.setProperty('--angle', String(state.angle)); ui.figure.style.setProperty('--angle', String(state.angle));
ui.figure.style.setProperty('--back-angle', String(state.backAngle));
ui.figure.style.setProperty('--leg-angle', String(state.legAngle));
ui.figure.style.setProperty('--head-angle', String(state.headAngle));
ui.figure.style.setProperty('--intensity', String(state.intensity)); ui.figure.style.setProperty('--intensity', String(state.intensity));
ui.figure.style.setProperty('--drift-x', `${driftX}px`); ui.figure.style.setProperty('--drift-x', `${driftX}px`);
ui.figure.style.setProperty('--drift-y', `${driftY}px`); ui.figure.style.setProperty('--drift-y', `${driftY}px`);
@ -128,6 +140,9 @@ document.addEventListener('DOMContentLoaded', () => {
const map = { const map = {
angleValue: `${state.angle}`, angleValue: `${state.angle}`,
anglePill: `${state.angle}°`, anglePill: `${state.angle}°`,
backAnglePill: `${state.backAngle}°`,
legAnglePill: `${state.legAngle}°`,
headAnglePill: `${state.headAngle}°`,
intensityPill: `${state.intensity}%`, intensityPill: `${state.intensity}%`,
statAngle: `${state.angle}°`, statAngle: `${state.angle}°`,
statIntensity: `${state.intensity}%`, statIntensity: `${state.intensity}%`,
@ -405,7 +420,7 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
} }
[controls.angle, controls.intensity].forEach((element) => { [controls.angle, controls.backAngle, controls.legAngle, controls.headAngle, controls.intensity].forEach((element) => {
if (element) { if (element) {
element.addEventListener('input', updateVisualization); element.addEventListener('input', updateVisualization);
element.addEventListener('change', updateVisualization); element.addEventListener('change', updateVisualization);

View File

@ -151,7 +151,7 @@ if (isset($_GET['saved']) && ctype_digit((string) $_GET['saved'])) {
<div class="axis-label axis-label-left">upright</div> <div class="axis-label axis-label-left">upright</div>
<div class="axis-label axis-label-right">full recline</div> <div class="axis-label axis-label-right">full recline</div>
<div class="motion-indicator" id="motion-state">Preview idle</div> <div class="motion-indicator" id="motion-state">Preview idle</div>
<div class="recliner-figure" id="recliner-figure" role="img" aria-label="3D recliner preview responding to angle and vibration settings" data-pattern="<?= e($formData['pattern_mode']) ?>" style="--angle: <?= e((string) $formData['angle_deg']) ?>; --intensity: <?= e((string) $formData['intensity_pct']) ?>;"> <div class="recliner-figure" id="recliner-figure" role="img" aria-label="3D recliner preview responding to angle and vibration settings" data-pattern="<?= e($formData['pattern_mode']) ?>" style="--angle: <?= e((string) $formData['angle_deg']) ?>; --intensity: <?= e((string) $formData['intensity_pct']) ?>; --back-angle: 0; --leg-angle: 0; --head-angle: 0;">
<div class="recliner-rig" aria-hidden="true"> <div class="recliner-rig" aria-hidden="true">
<div class="recliner-motion" id="recliner-motion"> <div class="recliner-motion" id="recliner-motion">
<div class="recliner-glow"></div> <div class="recliner-glow"></div>
@ -163,11 +163,11 @@ if (isset($_GET['saved']) && ctype_digit((string) $_GET['saved'])) {
<div class="recliner-seat-pad"></div> <div class="recliner-seat-pad"></div>
<div class="recliner-arm recliner-block"></div> <div class="recliner-arm recliner-block"></div>
<div class="recliner-arm recliner-arm-secondary recliner-block"></div> <div class="recliner-arm recliner-arm-secondary recliner-block"></div>
<div class="recliner-back recliner-block"></div> <div class="recliner-back recliner-block" id="part-back"></div>
<div class="recliner-back-inner"></div> <div class="recliner-back-inner" id="part-back-inner"></div>
<div class="recliner-head recliner-block"></div> <div class="recliner-head recliner-block" id="part-head"></div>
<div class="recliner-leg recliner-block"></div> <div class="recliner-leg recliner-block" id="part-leg"></div>
<div class="recliner-footpad recliner-block"></div> <div class="recliner-footpad recliner-block" id="part-footpad"></div>
</div> </div>
</div> </div>
<div class="angle-indicator"><span id="angle-value"><?= e((string) $formData['angle_deg']) ?></span><small>degrees</small></div> <div class="angle-indicator"><span id="angle-value"><?= e((string) $formData['angle_deg']) ?></span><small>degrees</small></div>
@ -190,9 +190,9 @@ if (isset($_GET['saved']) && ctype_digit((string) $_GET['saved'])) {
<section class="panel p-3 p-md-4"> <section class="panel p-3 p-md-4">
<div class="d-flex flex-wrap justify-content-between align-items-start gap-3 mb-4"> <div class="d-flex flex-wrap justify-content-between align-items-start gap-3 mb-4">
<div> <div>
<div class="small-label">Gamepad</div> <div class="small-label">Controls</div>
<h2 class="h4 mb-1">Haptic control surface</h2> <h2 class="h4 mb-1">Part and Haptic Controls</h2>
<p class="text-secondary mb-0">Select a connected controller, then test the current preset with one click.</p> <p class="text-secondary mb-0">Adjust individual recliner parts and test haptics.</p>
</div> </div>
<div class="gamepad-state" id="gamepad-state">Scanning for controllers…</div> <div class="gamepad-state" id="gamepad-state">Scanning for controllers…</div>
</div> </div>
@ -211,9 +211,21 @@ if (isset($_GET['saved']) && ctype_digit((string) $_GET['saved'])) {
<div class="control-stack"> <div class="control-stack">
<div class="control-group"> <div class="control-group">
<div class="d-flex justify-content-between align-items-center mb-2"><label for="angle_deg" class="form-label mb-0">Recline angle</label><span class="value-pill" id="angle-pill"><?= e((string) $formData['angle_deg']) ?>°</span></div> <div class="d-flex justify-content-between align-items-center mb-2"><label for="angle_deg" class="form-label mb-0">Overall Recline</label><span class="value-pill" id="angle-pill"><?= e((string) $formData['angle_deg']) ?>°</span></div>
<input type="range" class="form-range" min="0" max="160" step="1" id="angle_deg" name="angle_deg" value="<?= e((string) $formData['angle_deg']) ?>"> <input type="range" class="form-range" min="0" max="160" step="1" id="angle_deg" name="angle_deg" value="<?= e((string) $formData['angle_deg']) ?>">
</div> </div>
<div class="control-group">
<div class="d-flex justify-content-between align-items-center mb-2"><label for="back_angle" class="form-label mb-0">Back Adjustment</label><span class="value-pill" id="back-angle-pill">0°</span></div>
<input type="range" class="form-range" min="-20" max="20" step="1" id="back_angle" name="back_angle" value="0">
</div>
<div class="control-group">
<div class="d-flex justify-content-between align-items-center mb-2"><label for="leg_angle" class="form-label mb-0">Leg Adjustment</label><span class="value-pill" id="leg-angle-pill">0°</span></div>
<input type="range" class="form-range" min="-20" max="20" step="1" id="leg_angle" name="leg_angle" value="0">
</div>
<div class="control-group">
<div class="d-flex justify-content-between align-items-center mb-2"><label for="head_angle" class="form-label mb-0">Head Adjustment</label><span class="value-pill" id="head-angle-pill">0°</span></div>
<input type="range" class="form-range" min="-20" max="20" step="1" id="head_angle" name="head_angle" value="0">
</div>
<div class="control-group"> <div class="control-group">
<div class="d-flex justify-content-between align-items-center mb-2"><label for="intensity_pct" class="form-label mb-0">Vibration intensity</label><span class="value-pill" id="intensity-pill"><?= e((string) $formData['intensity_pct']) ?>%</span></div> <div class="d-flex justify-content-between align-items-center mb-2"><label for="intensity_pct" class="form-label mb-0">Vibration intensity</label><span class="value-pill" id="intensity-pill"><?= e((string) $formData['intensity_pct']) ?>%</span></div>
<input type="range" class="form-range" min="0" max="100" step="1" id="intensity_pct" name="intensity_pct" value="<?= e((string) $formData['intensity_pct']) ?>"> <input type="range" class="form-range" min="0" max="100" step="1" id="intensity_pct" name="intensity_pct" value="<?= e((string) $formData['intensity_pct']) ?>">