feat: node canvas grid
This commit is contained in:
@@ -6,6 +6,8 @@ class PresetControls extends Component {
|
||||
this.presets = {};
|
||||
this.currentPreset = null;
|
||||
this.presetControls = new Map();
|
||||
this.selectedNode = null; // Track which node is currently selected
|
||||
this.nodeParameters = new Map(); // Store parameters per node: nodeIp -> { presetName, parameters }
|
||||
}
|
||||
|
||||
mount() {
|
||||
@@ -80,28 +82,36 @@ class PresetControls extends Component {
|
||||
}
|
||||
|
||||
setupViewModelListeners() {
|
||||
this.subscribeToEvent('streamingStarted', (data) => {
|
||||
this.updateStreamingState(true, data.preset);
|
||||
// Listen for node selection
|
||||
this.subscribeToEvent('selectNode', (data) => {
|
||||
this.selectedNode = data.nodeIp;
|
||||
this.loadNodeSettings();
|
||||
});
|
||||
|
||||
this.subscribeToEvent('streamingStopped', () => {
|
||||
this.updateStreamingState(false);
|
||||
this.subscribeToEvent('streamingStarted', (data) => {
|
||||
this.updateStreamingState(true, data.preset, data.nodeIp);
|
||||
});
|
||||
|
||||
this.subscribeToEvent('streamingStopped', (data) => {
|
||||
this.updateStreamingState(false, null, data.nodeIp);
|
||||
});
|
||||
|
||||
this.subscribeToEvent('presetParameterUpdated', (data) => {
|
||||
// Update control display without triggering another update
|
||||
const control = this.presetControls.get(data.parameter);
|
||||
if (control) {
|
||||
if (control.type === 'range') {
|
||||
control.value = data.value;
|
||||
const valueDisplay = control.parentElement.querySelector('.preset-value');
|
||||
if (valueDisplay) {
|
||||
valueDisplay.textContent = parseFloat(data.value).toFixed(2);
|
||||
// Only update if this is for the currently selected node
|
||||
if (data.nodeIp === this.selectedNode) {
|
||||
const control = this.presetControls.get(data.parameter);
|
||||
if (control) {
|
||||
if (control.type === 'range') {
|
||||
control.value = data.value;
|
||||
const valueDisplay = control.parentElement.querySelector('.preset-value');
|
||||
if (valueDisplay) {
|
||||
valueDisplay.textContent = parseFloat(data.value).toFixed(2);
|
||||
}
|
||||
} else if (control.type === 'color') {
|
||||
control.value = this.hexToColorValue(data.value);
|
||||
} else {
|
||||
control.value = data.value;
|
||||
}
|
||||
} else if (control.type === 'color') {
|
||||
control.value = this.hexToColorValue(data.value);
|
||||
} else {
|
||||
control.value = data.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -202,9 +212,60 @@ class PresetControls extends Component {
|
||||
}
|
||||
|
||||
this.currentPreset = this.presets[presetName];
|
||||
|
||||
// Store preset selection for current node
|
||||
if (this.selectedNode) {
|
||||
const nodeParams = this.nodeParameters.get(this.selectedNode) || {};
|
||||
nodeParams.presetName = presetName;
|
||||
this.nodeParameters.set(this.selectedNode, nodeParams);
|
||||
}
|
||||
|
||||
this.createPresetControls();
|
||||
}
|
||||
|
||||
loadNodeSettings() {
|
||||
if (!this.selectedNode) return;
|
||||
|
||||
// Get stored parameters for this node
|
||||
const nodeParams = this.nodeParameters.get(this.selectedNode);
|
||||
|
||||
if (nodeParams && nodeParams.presetName) {
|
||||
// Load the preset and restore parameters
|
||||
const presetSelect = this.findElement('#preset-select');
|
||||
if (presetSelect && presetSelect.value !== nodeParams.presetName) {
|
||||
presetSelect.value = nodeParams.presetName;
|
||||
this.selectPreset(nodeParams.presetName);
|
||||
}
|
||||
|
||||
// Restore parameter values
|
||||
if (nodeParams.parameters) {
|
||||
Object.entries(nodeParams.parameters).forEach(([param, value]) => {
|
||||
const control = this.presetControls.get(param);
|
||||
if (control) {
|
||||
if (control.type === 'range') {
|
||||
control.value = value;
|
||||
const valueDisplay = control.parentElement.querySelector('.preset-value');
|
||||
if (valueDisplay) {
|
||||
valueDisplay.textContent = parseFloat(value).toFixed(2);
|
||||
}
|
||||
} else if (control.type === 'color') {
|
||||
control.value = this.hexToColorValue(value);
|
||||
} else {
|
||||
control.value = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Reset to default
|
||||
const presetSelect = this.findElement('#preset-select');
|
||||
if (presetSelect) {
|
||||
presetSelect.value = '';
|
||||
this.clearPresetControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createPresetControls() {
|
||||
const controlsContainer = this.findElement('#preset-controls');
|
||||
if (!controlsContainer) return;
|
||||
@@ -313,13 +374,24 @@ class PresetControls extends Component {
|
||||
}
|
||||
|
||||
updatePresetParameter(parameter, value) {
|
||||
// Store parameter for current node
|
||||
if (this.selectedNode) {
|
||||
const nodeParams = this.nodeParameters.get(this.selectedNode) || {};
|
||||
if (!nodeParams.parameters) {
|
||||
nodeParams.parameters = {};
|
||||
}
|
||||
nodeParams.parameters[parameter] = value;
|
||||
this.nodeParameters.set(this.selectedNode, nodeParams);
|
||||
}
|
||||
|
||||
// Send parameter update to server immediately (real-time)
|
||||
this.viewModel.publish('updatePresetParameter', {
|
||||
parameter,
|
||||
value
|
||||
value,
|
||||
nodeIp: this.selectedNode
|
||||
});
|
||||
|
||||
console.log(`Parameter updated: ${parameter} = ${value}`);
|
||||
console.log(`Parameter updated for ${this.selectedNode}: ${parameter} = ${value}`);
|
||||
}
|
||||
|
||||
clearPresetControls() {
|
||||
@@ -355,21 +427,39 @@ class PresetControls extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.selectedNode) {
|
||||
alert('Please select a node first');
|
||||
return;
|
||||
}
|
||||
|
||||
const width = parseInt(this.findElement('#matrix-width')?.value) || 16;
|
||||
const height = parseInt(this.findElement('#matrix-height')?.value) || 16;
|
||||
|
||||
// Get current parameters for this node
|
||||
const nodeParams = this.nodeParameters.get(this.selectedNode);
|
||||
const parameters = nodeParams?.parameters || {};
|
||||
|
||||
this.viewModel.publish('startPreset', {
|
||||
presetName: presetSelect.value,
|
||||
width,
|
||||
height
|
||||
height,
|
||||
nodeIp: this.selectedNode,
|
||||
parameters
|
||||
});
|
||||
}
|
||||
|
||||
stopStreaming() {
|
||||
this.viewModel.publish('stopStreaming', {});
|
||||
this.viewModel.publish('stopStreaming', {
|
||||
nodeIp: this.selectedNode
|
||||
});
|
||||
}
|
||||
|
||||
sendTestFrame() {
|
||||
if (!this.selectedNode) {
|
||||
alert('Please select a node first');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a test frame with a simple pattern in serpentine order
|
||||
const width = parseInt(this.findElement('#matrix-width')?.value) || 16;
|
||||
const height = parseInt(this.findElement('#matrix-height')?.value) || 16;
|
||||
@@ -390,12 +480,18 @@ class PresetControls extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
this.viewModel.publish('broadcastToAll', {
|
||||
this.viewModel.publish('sendToNode', {
|
||||
nodeIp: this.selectedNode,
|
||||
message: frameData
|
||||
});
|
||||
}
|
||||
|
||||
clearMatrix() {
|
||||
if (!this.selectedNode) {
|
||||
alert('Please select a node first');
|
||||
return;
|
||||
}
|
||||
|
||||
// Send a frame with all black pixels in serpentine order
|
||||
const width = parseInt(this.findElement('#matrix-width')?.value) || 16;
|
||||
const height = parseInt(this.findElement('#matrix-height')?.value) || 16;
|
||||
@@ -411,7 +507,8 @@ class PresetControls extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
this.viewModel.publish('broadcastToAll', {
|
||||
this.viewModel.publish('sendToNode', {
|
||||
nodeIp: this.selectedNode,
|
||||
message: frameData
|
||||
});
|
||||
}
|
||||
@@ -425,7 +522,12 @@ class PresetControls extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
updateStreamingState(isStreaming, preset) {
|
||||
updateStreamingState(isStreaming, preset, nodeIp) {
|
||||
// Only update UI if this is for the currently selected node
|
||||
if (nodeIp !== this.selectedNode && nodeIp !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toggleBtn = this.findElement('#toggle-stream-btn');
|
||||
const btnIcon = toggleBtn?.querySelector('.btn-icon');
|
||||
const btnText = toggleBtn?.querySelector('.btn-text');
|
||||
|
||||
Reference in New Issue
Block a user