Implement global axis system and advanced motion logic

This commit is contained in:
2025-12-21 23:25:23 +09:00
parent 182c364e37
commit a459b81884
7 changed files with 802 additions and 365 deletions

View File

@@ -1,4 +1,5 @@
import React from 'react';
import { AxisData } from '../types';
interface IOPanelProps {
inputs: boolean[];
@@ -7,21 +8,25 @@ interface IOPanelProps {
outputNames: string[];
onToggleInput: (index: number) => void;
onToggleOutput: (index: number) => void;
axes: AxisData[];
setAxes: React.Dispatch<React.SetStateAction<AxisData[]>>;
}
export const IOPanel: React.FC<IOPanelProps> = ({
inputs,
outputs,
inputNames,
export const IOPanel: React.FC<IOPanelProps> = ({
inputs,
outputs,
inputNames,
outputNames,
onToggleInput,
onToggleOutput
onToggleOutput,
axes,
setAxes
}) => {
const renderBits = (
bits: boolean[],
names: string[],
colorClass: string,
label: string,
bits: boolean[],
names: string[],
colorClass: string,
label: string,
onToggle: (i: number) => void
) => (
<div className="mb-6">
@@ -29,14 +34,13 @@ export const IOPanel: React.FC<IOPanelProps> = ({
<div className="grid grid-cols-4 gap-2">
{bits.map((isActive, i) => (
<div key={i} className="flex flex-col items-center group relative">
<button
<button
onClick={() => onToggle(i)}
title={`${label} ${i}: ${names[i] || 'Unnamed'}`}
className={`w-7 h-7 rounded-md border border-gray-700 flex items-center justify-center text-[10px] font-mono transition-all duration-150 active:scale-90 ${
isActive
? `${colorClass} shadow-[0_0_10px_rgba(255,255,255,0.3)] border-transparent text-black font-bold`
: 'bg-gray-850 text-gray-500 hover:bg-gray-700'
}`}
className={`w-7 h-7 rounded-md border border-gray-700 flex items-center justify-center text-[10px] font-mono transition-all duration-150 active:scale-90 ${isActive
? `${colorClass} shadow-[0_0_10px_rgba(255,255,255,0.3)] border-transparent text-black font-bold`
: 'bg-gray-850 text-gray-500 hover:bg-gray-700'
}`}
>
{i}
</button>
@@ -56,7 +60,7 @@ export const IOPanel: React.FC<IOPanelProps> = ({
<div className="w-2 h-2 rounded-full bg-blue-500 animate-pulse" />
I/O Monitor
</h2>
{renderBits(inputs, inputNames, 'bg-green-500', 'Inputs', onToggleInput)}
<hr className="border-gray-800 my-4" />
{renderBits(outputs, outputNames, 'bg-red-500', 'Outputs', onToggleOutput)}
@@ -66,6 +70,33 @@ export const IOPanel: React.FC<IOPanelProps> = ({
<p> Click bits to toggle state</p>
<p> Hover to see port names</p>
</div>
<div className="flex-1 overflow-auto p-2" style={{ maxHeight: '20vh' }}>
<h4 className="text-[10px] uppercase text-blue-500 font-bold mb-2 sticky top-0 bg-gray-900/90 backdrop-blur pb-1 z-10">Axis Channels</h4>
<div className="space-y-2">
{axes.map((axis, i) => (
<div key={i} className="flex flex-col gap-1 p-2 bg-gray-800/50 rounded border border-gray-700">
<div className="flex justify-between items-center">
<span className="text-[10px] text-gray-400 font-mono">CH{i}</span>
<span className="text-[10px] text-white font-bold truncate max-w-[80px]" title={axis.name}>{axis.name}</span>
<span className="text-[10px] text-blue-400 font-mono">{axis.value.toFixed(1)}</span>
</div>
{/* Miniature Slider for quick view/control */}
<input
type="range"
min={0}
max={axis.type === 'rotary' ? 360 : 100}
value={axis.value}
onChange={(e) => {
const val = parseFloat(e.target.value);
setAxes(prev => prev.map((a, idx) => idx === i ? { ...a, value: val, target: val } : a));
}}
className="w-full h-1 bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-500"
/>
</div>
))}
</div>
</div>
</div>
);
};