Files
2025-04-06 12:54:48 -04:00

158 lines
5.7 KiB
JavaScript

/**
* Controller button functionality for ComfyUI_ControlFreak
*/
import { app } from "../../../../scripts/app.js";
import { showNotification } from './notifications.js';
import { contextProvider } from '../core/contextProvider.js';
import { eventBus } from '../core/eventBus.js';
import { toggleMappingUI } from './mappingPanel.js';
/**
* Add the controller management button to the UI
*/
export async function addControllerButton() {
try {
// Find the ComfyUI header
const menu = document.querySelector(".comfy-menu");
if (!menu) {
console.warn("ControlFreak: Could not find ComfyUI header menu");
return;
}
// Add a separator
const separator = document.createElement("hr");
separator.className = "cf-menu-separator";
menu.append(separator);
// Create the click handler
const handleClick = () => {
// Get controllers from context provider
const midiController = contextProvider.get('midiController');
const gamepadController = contextProvider.get('gamepadController');
const mappingEngine = contextProvider.get('mappingEngine');
if (!midiController || !gamepadController) {
showNotification("Controller system not fully initialized", 'error');
return;
}
// Show the mapping panel
toggleMappingUI(true);
// Emit event for analytics
eventBus.emit('ui:controllerButtonClicked');
};
try {
// Import the ComfyButtonGroup for proper integration
const { ComfyButtonGroup } = await import("../../../../scripts/ui/components/buttonGroup.js");
// Create our branded button
const controlFreakButton = document.createElement("button");
controlFreakButton.className = "cf-menu-button";
controlFreakButton.id = "controlfreak-menu-button";
controlFreakButton.title = "Control Freak - Map your controllers to ComfyUI";
// Add the branded text
const brandText = document.createElement("span");
brandText.className = "cf-brand-text";
brandText.innerHTML = 'Control<span class="cf-brand-highlight">Freak</span>';
controlFreakButton.appendChild(brandText);
// Set click handler
controlFreakButton.onclick = handleClick;
// Create a wrapper for proper menu integration
const buttonWrapper = document.createElement("div");
buttonWrapper.className = "comfyui-tool-group cf-button-wrapper";
buttonWrapper.appendChild(controlFreakButton);
// Insert before settings group
app.menu?.settingsGroup.element.before(buttonWrapper);
}
catch(exception) {
console.error('ControlFreak: Error adding button to menu:', exception);
}
// Set up event handling for controller connections
setupControllerEvents();
// Set up handler to update button state when controllers connect
updateButtonState();
} catch (error) {
console.error("ControlFreak: Error adding controller button:", error);
}
}
/**
* Update button state based on connected controllers
*/
function updateButtonState() {
const button = document.querySelector('#controlfreak-menu-button');
if (!button) return;
const midiController = contextProvider.get('midiController');
const gamepadController = contextProvider.get('gamepadController');
// Count total connected controllers
let connectedCount = 0;
if (midiController) {
const midiInputs = midiController.getInputs();
connectedCount += midiInputs.filter(d => d.state === 'connected').length;
}
if (gamepadController) {
const gamepads = gamepadController.getGamepads();
connectedCount += gamepads.filter(d => d.state === 'connected').length;
}
// Update button state
if (connectedCount > 0) {
button.classList.add('connected');
button.title = `${connectedCount} controller${connectedCount > 1 ? 's' : ''} connected`;
} else {
button.classList.remove('connected');
button.title = 'No controllers connected';
}
}
/**
* Set up handler functions for controller events
*/
function setupControllerEvents() {
// Set up event handlers for controller connections
eventBus.on('midi:deviceConnected', (device) => {
showNotification(`MIDI Device Connected: ${device.deviceName}`, 'success');
updateButtonState();
});
eventBus.on('midi:deviceDisconnected', (device) => {
showNotification(`MIDI Device Disconnected: ${device.deviceName}`, 'info');
updateButtonState();
});
eventBus.on('gamepad:deviceConnected', (device) => {
showNotification(`Gamepad Connected: ${device.deviceName}`, 'success');
updateButtonState();
});
eventBus.on('gamepad:deviceDisconnected', (device) => {
showNotification(`Gamepad Disconnected: ${device.deviceName}`, 'info');
updateButtonState();
});
// State changes
eventBus.on('midi:stateChanged', () => updateButtonState());
eventBus.on('gamepad:stateChanged', () => updateButtonState());
// Error handling
eventBus.on('midi:error', (error) => {
showNotification(`MIDI Error: ${error.message}`, 'error');
});
eventBus.on('gamepad:error', (error) => {
showNotification(`Gamepad Error: ${error.message}`, 'error');
});
}