scepter Posted September 9, 2018 Share Posted September 9, 2018 Will there be any third party support for it anytime soon? I really loved the ability to do that with cue 2 hoping it come's to iCUE . Link to comment Share on other sites More sharing options...
jsm Posted December 14, 2018 Share Posted December 14, 2018 Come on Corsair, why don't you answer this question??? Link to comment Share on other sites More sharing options...
hastegag Posted December 14, 2018 Share Posted December 14, 2018 (edited) the wallpaper engine basically works with this and there are a couple spectrograph or eq sdk things out there i think. The wallpaper engine one is a bit nicer though (that said as typing this i realized it wasnt working or it pauses when ANY other application has been maximized...seems like a bug or something). As JSM posted elsewhere, its a bit esoteric with the two examples I have seen as they are basically minimized js in a webpage that must have some type of magic via a SDK wrapper. couple folks on here in cue2 era did some wrappers of the sdk in .net or node.js We could probably figure out how to tweak it, I may try throwing the minimized one into http://jsnice.org/ and see what comes out Oops forget all that noise above, i found the main.js in the projects\defaultprojects\corsair_o_tron\js\ folder after webtools inspection per steam guide...may make edits much easier, looking into it Edit 2 around line 199 i added: mousematContext.fillStyle = barColor.darken(5).hex(); //https://gka.github.io/chroma.js/ and hroma('orange').hex() == "#ffa500" and around line 236: peakColor = audioScale(totalPeak.value).rgb(); //{0.2,0.2,0.2}; //needs gl ending?? only if not normalized with sdk? peakColor[0] *= 0.1; peakColor[1] *= 0.1; peakColor[2] *= 0.1; //mutes all other colors like st100, they were a bit bright and static detraction its fun toying with this. Still the full-screen bug leaves one unfulfilled, not sure what's up there. A LOT more can / could be done here, possibilities are endless. Edited December 14, 2018 by hastegag Link to comment Share on other sites More sharing options...
hastegag Posted December 15, 2018 Share Posted December 15, 2018 I added the headset stand to corsair o tron using the mouse pad as a guide. index.html looks like: <!DOCTYPE html> <html> <head> <title>Corsair Corsair-o-Tron</title> <style> body { margin: 0; } #logo-container { width: 48vh; /* 20% of the viewport width */ height: 48vh; position: fixed; top: 8%; left: 42%; display: flex; justify-content: center; align-items: center; } #logo { background-color: black; -webkit-mask-image: url(images/Logo.svg); -webkit-mask-repeat: no-repeat; mask-image: url(images/Logo.svg); mask-repeat: no-repeat; position: absolute; width: 38%; height: 38%; } #ring1 { background-color: black; -webkit-mask-image: url(images/Asset_1.svg); mask-image: url(images/Asset_1.svg); position: absolute; width: 78%; height: 78%; -webkit-animation: rotate-right 10s linear infinite; } #ring2 { background-color: black; -webkit-mask-image: url(images/Asset_2.svg); mask-image: url(images/Asset_2.svg); position: absolute; width: 100%; height: 100%; -webkit-animation: rotate-left 10s linear infinite; } #ring3 { background-color: black; -webkit-mask-image: url(images/Asset_3.svg); mask-image: url(images/Asset_3.svg); position: absolute; width: 97%; height: 97%; } #robot { background-size: contain; background-repeat: no-repeat; background-image: url(images/bot_bw.png); position: fixed; top: 5%; right: 0; left: 60%; height: 90%; } #renderCanvas { width: 100vw; height: 100vh; display: block; background: #000000; } #keyboardCanvas { display: none; background: #000000; } #mousematCanvas { display: none; background: #000000; } #headsetStandCanvas { display: none; background: #000000; } #nodeCanvas { display: none; background: #000000; } @-webkit-keyframes rotate-right { from { -webkit-transform: rotate(0deg); } to { -webkit-transform: rotate(360deg); } } @-webkit-keyframes rotate-left { from { -webkit-transform: rotate(360deg); } to { -webkit-transform: rotate(0deg); } } </style> </head> <body> <div id="logo-container"> <div id="logo"></div> <div id="ring1"></div> <div id="ring2"></div> <div id="ring3"></div> </div> <div id="robot"></div> <canvas id="keyboardCanvas"></canvas> <canvas id="mousematCanvas"></canvas> <canvas id="headsetStandCanvas"></canvas> <canvas id="nodeCanvas"></canvas> <canvas id="renderCanvas"></canvas> </body> <script src="./js/chroma.min.js"></script> <script src="./js/TweenMax.min.js"></script> <script src="./js/math.min.js"></script> <script src="./js/main.js"></script> </html> and main.js looks like this: var chroma = window.chroma; var TweenMax = window.TweenMax; // General variables var running = false; var turnSpeed = 0.1; var rainbowRotation = 0; var audioArray = []; var totalPeak = {value: 0}; var leftPeak = {value: 0}; var rightPeak = {value: 0}; var audioScale = chroma.scale([ chroma('white'), chroma('black')] ); var logo = document.getElementById('logo'); var ring1 = document.getElementById('ring1'); var ring2 = document.getElementById('ring2'); var ring3 = document.getElementById('ring3'); var colorStops = [ {stopPercent: 0.1428571428571429, color: '#ff0000'}, {stopPercent: 0.2857142857142857, color: '#ffea00'}, {stopPercent: 0.4285714285714286, color: '#6fff00'}, {stopPercent: 0.5714285714285715, color: '#00fbff'}, {stopPercent: 0.7142857142857144, color: '#0001ff'}, {stopPercent: 0.8571428571428573, color: '#ff00f5'}, {stopPercent: 1, color: '#ff0000'} ]; // CUE variables var cue = null; var cueKeyboardIndex = null; var cueMouseMatIndex = null; var cueNodeIndices = null; var cueOtherIndices = null; // Settings var fps = 60; var backgroundColor = chroma('white'); var barColor = chroma('black'); var bottomColor = chroma('#8c8c8c'); var useRainbow = false; var cycleRainbow = false; var barHeight = 250; var barSpacing = 6; var sensitivity = 1.0; var peakSensitivity = 1.0; var bottomHeight = 150; var calculationType = 'max'; // Get the canvas var canvas = document.getElementById('renderCanvas'); var keyboardCanvas = document.getElementById('keyboardCanvas'); var mousematCanvas = document.getElementById('mousematCanvas'); var headsetStandCanvas = document.getElementById('headsetStandCanvas'); var nodeCanvas = document.getElementById('nodeCanvas'); var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); // window.devicePixelRatio doesn't seem reliable in CEF var scale = window.devicePixelRatio; if (scale === 1) { // 1080p if (h === 1080) { scale = 1; } // 1440p else if (h === 1440) { scale = 1.25; } // 4k else if (h >= 2160) { scale = 1.5; } canvas.width = w; canvas.height = h; } else { canvas.width = w * scale; canvas.height = h * scale; } // Robot div var robot = document.getElementById('robot'); function start() { if (running) { return; } renderLoop = setInterval(onTimerTick, 1000 / fps); running = true; } function stop() { if (!running) { return; } clearInterval(renderLoop); running = false; } function onTimerTick() { var context = canvas.getContext('2d'); // context.scale(scale, scale); // Clear the canvas context.clearRect(0, 0, canvas.width, canvas.height); context.fillStyle = backgroundColor.hex(); context.fillRect(0, 0, canvas.width, canvas.height); // Debug info in the top left, can be useful //context.fillStyle = 'white'; //context.font = '30px Arial'; //context.fillText(totalPeak.value.toString(), 50, 50); //context.fillText(corsairColor.toString(),50,50); if (useRainbow) { context.fillStyle = getRainbowGradient(canvas, context); } else { context.fillStyle = barColor.hex(); // chroma(0.6, 0, 0.8, 'gl'); and chroma('orange').hex() //https://gka.github.io/chroma.js/ } var scaledBottomHeight = bottomHeight * scale; // Render bars along the full width of the canvas with 5 pixels of space between them var barWidth = Math.round(1 / 64 * canvas.width); for (var i = 0; i < 64; i++) { var x = ((barWidth) * i) + (barSpacing / 2); var y = canvas.height - scaledBottomHeight; if (audioArray[i]) { var height = barHeight * scale * audioArray[i].value; //me edit scale cranking x 4 above context.fillRect(x, y - height, barWidth - barSpacing, height); } } // Render the bottom context.fillStyle = bottomColor.hex(); context.fillRect(0, canvas.height - scaledBottomHeight, canvas.width, scaledBottomHeight); if (cycleRainbow) { if (rainbowRotation > 360) { rainbowRotation = 0; } rainbowRotation = rainbowRotation + (turnSpeed * 30 / fps); } // If CUE not detected the update is done here if (cue === null) { return; } // Update CUE devices // Render all bars to the keyboard just like on the wallpaper var imageData = null; if (cueKeyboardIndex !== null) { // Take samples of the audio data var sampleSize = Math.round(audioArray.length / keyboardCanvas.width); var samplesLeft = audioArray.length; var count = 0; var keyboardContext = keyboardCanvas.getContext('2d'); keyboardContext.clearRect(0, 0, keyboardCanvas.width, keyboardCanvas.height); keyboardContext.fillStyle = backgroundColor.hex(); keyboardContext.fillRect(0, 0, keyboardCanvas.width, keyboardCanvas.height); if (useRainbow) { keyboardContext.fillStyle = getRainbowGradient(keyboardCanvas, keyboardContext); } else { keyboardContext.fillStyle = barColor.hex(); } while (samplesLeft > 0) { var sampleSum = 0; for (var s = 0; s < Math.min(sampleSize, samplesLeft); ++s) { sampleSum = sampleSum + audioArray[s + (count * sampleSize)].value; } var sampleRes = sampleSum / Math.min(sampleSize, samplesLeft); var keyboardBarHeight = keyboardCanvas.height * sampleRes; keyboardContext.fillRect(count, keyboardCanvas.height - keyboardBarHeight, 1, keyboardBarHeight); samplesLeft = samplesLeft - sampleSize; count++; } // Map the image data to keyboard imageData = getEncodedCanvasImageData(keyboardCanvas); cue.setLedColorsByImageData(cueKeyboardIndex, imageData, keyboardCanvas.width, keyboardCanvas.height); } // Render two side bars for mousemats, for left and right channel if (cueMouseMatIndex !== null) { var mousematContext = mousematCanvas.getContext('2d'); mousematContext.clearRect(0, 0, mousematCanvas.width, mousematCanvas.height); mousematContext.fillStyle = backgroundColor.hex(); mousematContext.fillRect(0, 0, mousematCanvas.width, mousematCanvas.height); if (useRainbow) { mousematContext.fillStyle = getRainbowGradient(mousematCanvas, mousematContext); } else { //console.log("") mousematContext.fillStyle = barColor.darken(5).hex(); //https://gka.github.io/chroma.js/ and hroma('orange').hex() == "#ffa500" } var leftBarHeight = mousematCanvas.height * leftPeak.value; var rightBarHeight = mousematCanvas.height * rightPeak.value; mousematContext.fillRect(0, mousematCanvas.height - leftBarHeight, mousematCanvas.width / 2, leftBarHeight); mousematContext.fillRect(mousematCanvas.width / 2, mousematCanvas.height - rightBarHeight, mousematCanvas.width / 2, rightBarHeight); imageData = getEncodedCanvasImageData(mousematCanvas); cue.setLedColorsByImageData(cueMouseMatIndex, imageData, mousematCanvas.width, mousematCanvas.height); } // Render two side bars for HeadsetStand, for left and right channel if (cueHeadsetStandIndex !== null) { var headsetStandContext = headsetStandCanvas.getContext('2d'); headsetStandContext.clearRect(0, 0, headsetStandCanvas.width, headsetStandCanvas.height); headsetStandContext.fillStyle = backgroundColor.hex(); headsetStandContext.fillRect(0, 0, headsetStandCanvas.width, headsetStandCanvas.height); if (useRainbow) { headsetStandContext.fillStyle = getRainbowGradient(headsetStandCanvas, headsetStandContext); } else { headsetStandContext.fillStyle = barColor.darken(5).hex(); } var leftBarHeight2 = headsetStandCanvas.height * leftPeak.value; var rightBarHeight2 = headsetStandCanvas.height * rightPeak.value; headsetStandContext.fillRect(0, headsetStandCanvas.height - leftBarHeight2, headsetStandCanvas.width / 2, leftBarHeight2); headsetStandContext.fillRect(headsetStandCanvas.width / 2, headsetStandCanvas.height - rightBarHeight2, headsetStandCanvas.width / 2, rightBarHeight2); imageData = getEncodedCanvasImageData(headsetStandCanvas); cue.setLedColorsByImageData(cueHeadsetStandIndex, imageData, headsetStandCanvas.width, headsetStandCanvas.height); } if (cueNodeIndices !== null && cueNodeIndices.length) { var nodeContext = nodeCanvas.getContext('2d'); nodeContext.clearRect(0, 0, nodeCanvas.width, nodeCanvas.height); nodeContext.fillStyle = backgroundColor.hex(); nodeContext.fillRect(0, 0, nodeCanvas.width, nodeCanvas.height); if (useRainbow) { nodeContext.fillStyle = getRainbowGradient(nodeCanvas, nodeContext); } else { nodeContext.fillStyle = barColor.hex(); } nodeContext.fillRect(0, 0, nodeCanvas.width * totalPeak.value, 4); //me edits made it an eight seems to boost the light intensity on the mousepad imageData = getEncodedCanvasImageData(nodeCanvas); cueNodeIndices.forEach(function (index) { cue.setLedColorsByImageData(index, imageData, nodeCanvas.width, nodeCanvas.height); }); } // Assign the color scaled to the peak to all other LEDs cueOtherIndices.forEach(function (index) { var peakColor; if (useRainbow) { peakColor = chroma((totalPeak.value * 60) + (index * 45) + rainbowRotation, 1, 0.5, 'hsl').rgb(); } else { peakColor = audioScale(totalPeak.value).rgb(); //{0.2,0.2,0.2}; //needs gl ending due to api //peakColor[0] *= 0.1; //peakColor[1] *= 0.1; //peakColor[2] *= 0.1; //mutes all other colors like st100, they were a bit bright and static detraction } var corsairColor = {r: peakColor[0], g: peakColor[1], b: peakColor[2]}; window.cue.setAllLedsColorsAsync(index, corsairColor); }); } start(); function getRainbowGradient(canvas, context) { var gradient = context.createLinearGradient((canvas.width * 0.2) * -1, 0, canvas.width * 1.4, canvas.height); for (var i = 0; i < colorStops.length; i++) { var tempColorStop = colorStops[i]; var tempColor = tempColorStop.color; var tempStopPercent = tempColorStop.stopPercent; gradient.addColorStop(tempStopPercent, tempColor); if (cycleRainbow) { tempStopPercent += (0.0001 * fps / 60); if (tempStopPercent > 1) { tempStopPercent = 0; } tempColorStop.stopPercent = tempStopPercent; } colorStops[i] = tempColorStop; } return gradient; } function getEncodedCanvasImageData(canvas) { var context = canvas.getContext('2d'); var imageData = context.getImageData(0, 0, canvas.width, canvas.height); var colorArray = []; for (var d = 0; d < imageData.data.length; d += 4) { var write = d / 4 * 3; colorArray[write] = imageData.data[d]; colorArray[write + 1] = imageData.data[d + 1]; colorArray[write + 2] = imageData.data[d + 2]; } return String.fromCharCode.apply(null, colorArray); } function wallpaperAudioListener(audioData) { var newTotalPeak = 0; var newLeftPeak = 0; var newRightPeak = 0; var audioDataAverage = []; var halfWayThough = Math.floor(audioData.length / 2); var left = audioData.slice(0, halfWayThough); var right = audioData.slice(halfWayThough, audioData.length); // Calculate according to calculation type, default to max if (calculationType === 'median') { newTotalPeak = math.median(audioData); newLeftPeak = math.median(left); newRightPeak = math.median(right); } else if (calculationType === 'mean') { newTotalPeak = math.mean(audioData); newLeftPeak = math.mean(left); newRightPeak = math.mean(right); } else if (calculationType === 'average') { newTotalPeak = math.sum(audioData) / audioData.length; newLeftPeak = math.sum(left) / left.length; newRightPeak = math.sum(right) / right.length; } else { newTotalPeak = math.max(audioData); newLeftPeak = math.max(left); newRightPeak = math.max(right); } for (var i = 0; i < audioData.length; ++i) { // Average out two values if (i % 2) { audioDataAverage.push((audioData[i - 1] + audioData[i]) / 2 * sensitivity) } } // Assign the new audio peak TweenMax.to(totalPeak, 0.2, {value: newTotalPeak * peakSensitivity}); TweenMax.to(leftPeak, 0.2, {value: newLeftPeak * sensitivity}); TweenMax.to(rightPeak, 0.2, {value: newRightPeak * sensitivity}); // Transform the old data into the new for (var j = 0; j < audioDataAverage.length; ++j) { // If this is a fresh set of data, apply it if (!audioArray[j]) { audioArray.push({value: audioDataAverage[j]}); } // If updating, tween between old and new else { TweenMax.to(audioArray[j], 0.2, {value: audioDataAverage[j]}); } } } window.wallpaperPropertyListener = { applyGeneralProperties: function (properties) { if (properties.fps) { // Restart the render loop at the new FPS if it is changed if (fps !== properties.fps) { fps = properties.fps; stop(); start(); } } }, applyUserProperties: function (properties) { if (properties.schemecolor) { var barColors = properties.schemecolor.value.split(' '); barColor = chroma(barColors[0], barColors[1], barColors[2], 'gl'); } if (properties.logocolor) { var logoColors = properties.logocolor.value.split(' '); var logoColor = chroma(logoColors[0], logoColors[1], logoColors[2], 'gl'); logo.style.backgroundColor = logoColor.css(); ring1.style.backgroundColor = logoColor.css(); ring2.style.backgroundColor = logoColor.css(); ring3.style.backgroundColor = logoColor.css(); } if (properties.logorings) { if (properties.logorings.value === true) { logo.style.width = '38%'; logo.style.height = '38%'; ring1.style.display = 'block'; ring2.style.display = 'block'; ring3.style.display = 'block'; } else { logo.style.width = '60%'; logo.style.height = '60%'; ring1.style.display = 'none'; ring2.style.display = 'none'; ring3.style.display = 'none'; } } if (properties.backgroundcolor) { var bgColors = properties.backgroundcolor.value.split(' '); backgroundColor = chroma(bgColors[0], bgColors[1], bgColors[2], 'gl'); } if (properties.showbottom) { bottomHeight = properties.showbottom.value; } if (properties.bottomcolor) { var bottomColors = properties.bottomcolor.value.split(' '); bottomColor = chroma(bottomColors[0], bottomColors[1], bottomColors[2], 'gl'); } if (properties.rainbowscheme) { useRainbow = properties.rainbowscheme.value; } if (properties.cyclerainbow) { cycleRainbow = properties.cyclerainbow.value; } if (properties.colorized) { if (properties.colorized.value === true) { robot.style.backgroundImage = 'url(images/bot_color.png)'; } else { robot.style.backgroundImage = 'url(images/bot_bw.png)'; } } if (properties.sensitivity) { sensitivity = properties.sensitivity.value; } if (properties.peaksensitivity) { peakSensitivity = properties.peaksensitivity.value; } if (properties.calculationtype) { calculationType = properties.calculationtype.value; } }, setPaused: function (isPaused) { if (isPaused) { stop(); } else { start(); } } }; window.wallpaperRegisterAudioListener(wallpaperAudioListener); window.wallpaperPluginListener = { onPluginLoaded: function (name, version) { if (name === 'cue') { cueOtherIndices = []; cueNodeIndices = []; var onDeviceInfoReceived = function (deviceIndex, deviceInfo) { if (deviceInfo.type === 'CDT_Keyboard') { // Create a canvas that matches the keyboard's physical key columns and rows switch (deviceInfo.model) { case 'K95 RGB': keyboardCanvas.height = 7; keyboardCanvas.width = 25; break; case 'K95 RGB PLATINUM': keyboardCanvas.height = 9; keyboardCanvas.width = 22; break; case 'K70 RGB': case 'K70 RGB RAPIDFIRE': case 'K70 LUX RGB': keyboardCanvas.height = 7; keyboardCanvas.width = 21; break; case 'K65 RGB': case 'CGK65 RGB': case 'K65 LUX RGB': case 'K65 RGB RAPIDFIRE': keyboardCanvas.height = 7; keyboardCanvas.width = 18; break; case 'STRAFE RGB': keyboardCanvas.height = 8; keyboardCanvas.width = 22; break; // Default to the K70 since that's a standard keyboard default: keyboardCanvas.height = 7; keyboardCanvas.width = 21; break; } cueKeyboardIndex = deviceIndex; } else if (deviceInfo.type === 'CDT_MouseMat') { mousematCanvas.height = 10; mousematCanvas.width = 10; cueMouseMatIndex = deviceIndex; } else if (deviceInfo.type === 'CDT_HeadsetStand') { headsetStandCanvas.height = 2; headsetStandCanvas.width = 9; cueHeadsetStandIndex = deviceIndex; } else if (deviceInfo.type === 'CDT_LightingNodePro' || deviceInfo.type === 'CDT_CommanderPro') { nodeCanvas.height = 2; nodeCanvas.width = 25; cueNodeIndices.push(deviceIndex); } else { cueOtherIndices.push(deviceIndex); } console.log(deviceInfo.type); }; window.cue.getDeviceCount(function (deviceCount) { for (var d = 0; d < deviceCount; ++d) { (function (d) { window.cue.getDeviceInfo(d, function (deviceInfo) { onDeviceInfoReceived(d, deviceInfo); }); }(d)); } }); cue = window.cue; } } }; seems to work reasonably well. Not rocket science changes but probably worth doing if you use it and have a headset stand. Link to comment Share on other sites More sharing options...
hastegag Posted December 15, 2018 Share Posted December 15, 2018 http://forum.corsair.com/v3/showthread.php?t=183531 PJH brought to my attention the void visualizer, which is pretty neat but only appears to work on the keyboard. Link to comment Share on other sites More sharing options...
Recommended Posts