(function () { var MENU_NAME = "line up assets on track"; // selection helpers function getSelectedTrack() { var sel = studio.window.editorSelection() || []; for (var i = 0; i < sel.length; i++) { var o = sel[i]; if (!o) continue; if (o.isOfType("GroupTrack")) return o; if (o.isOfType("EventMixerGroup") && o.groupTrack) return o.groupTrack; } for (var j = 0; j < sel.length; j++) { var m = sel[j]; if (m && m.isOfType("Module") && m.audioTrack && m.audioTrack.isOfType("GroupTrack")) return m.audioTrack; } return null; } function getSelectedModuleSheet() { var sel = studio.window.editorSelection() || []; for (var i = 0; i < sel.length; i++) { var m = sel[i]; if (m && m.isOfType("Module") && m.parameter) return m.parameter; } return null; } function getSelectedAudioFiles() { var sel = studio.window.browserSelection("Assets") || []; var files = [], seen = {}; function add(af) { if (!seen[af.id]) { seen[af.id] = true; files.push(af); } } sel.forEach(function (item) { if (!item) return; if (item.isOfType("AudioFile")) { add(item); } else if (item.isOfType("Asset")) { // Folder: include every audio file beneath it, sorted by path. var prefix = item.getAssetPath(); if (prefix && prefix.charAt(prefix.length - 1) !== "/") prefix += "/"; studio.project.model.AudioFile.findInstances() .filter(function (af) { return af.getAssetPath().indexOf(prefix) === 0; }) .sort(function (a, b) { return a.getAssetPath() < b.getAssetPath() ? -1 : 1; }) .forEach(add); } }); return files; } // find viewed sheet function getActiveSheet(event) { var s = event.uiLastParameterSelection; if (s && s.isValid) return s; s = getSelectedModuleSheet(); if (s && s.event && s.event.id === event.id) return s; return event.timeline; } // placement function sheetRange(sheet) { var gp = sheet.preset; return { min: gp.minimum, max: gp.maximum, name: gp.presetOwner ? gp.presetOwner.name : "parameter" }; } function placeOnTimeline(event, track, files) { var pos = event.getCursorPosition(event.timeline); if (typeof pos !== "number" || isNaN(pos) || pos < 0) pos = 0; var placed = 0, skipped = []; files.forEach(function (af) { var len = af.length; if (typeof len !== "number" || !(len > 0)) { skipped.push(af.getAssetPath()); return; } var s = track.addSound(event.timeline, "SingleSound", pos, len); s.audioFile = af; pos += len; placed++; }); return { placed: placed, skipped: skipped }; } function placeOnSheet(sheet, track, files) { var r = sheetRange(sheet); var width = (r.max - r.min) / files.length; files.forEach(function (af, i) { var s = track.addSound(sheet, "SingleSound", r.min + i * width, width); s.audioFile = af; }); return { placed: files.length, skipped: [] }; } // menu function run() { var track = getSelectedTrack(); if (!track) { alert("Select an audio track in the event editor."); return; } var event = track.event; if (!event || !event.isOfType("Event")) { alert("couldn't determine event for selected track"); return; } var files = getSelectedAudioFiles(); if (!files.length) { alert("select one or more audio files in assets browser"); return; } var sheet = getActiveSheet(event); var result; if (sheet.isOfType("Timeline")) { result = placeOnTimeline(event, track, files); } else if (sheet.isOfType("ParameterProxy")) { var r = sheetRange(sheet); if (!(r.max > r.min)) { alert("Parameter sheet '" + r.name + "' has an empty range."); return; } result = placeOnSheet(sheet, track, files); } else { return; } var where = sheet.isOfType("Timeline") ? "the timeline" : "'" + sheetRange(sheet).name + "'"; console.log("{0}: placed {1} of {2} file(s) on track '{3}' ({4}).".format(MENU_NAME, result.placed, files.length, track.mixerGroup.name, where)); if (result.skipped.length) { alert("Placed {0} of {1} files. Skipped (unknown length):\n{2}".format(result.placed, files.length, result.skipped.join("\n"))); } } studio.menu.addMenuItem({ name: MENU_NAME, execute: run, }); })();