SequenceMgr.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*
  2. SEQUENCE GROUPING MANAGEMENT MODULE
  3. this module builds a representation of a sequence in values using containers
  4. It allows to create groups of keys, a group being a cue and one key per layer.
  5. In a group, all keys sync their time on cue's time, only value can be modified
  6. The sequence with grouping can then be exported and reloaded.
  7. The module checks periodicaly if timeline sequence structure (cues, layers and keys) and
  8. module values structure are in sync. If out of sync, you may either rebuild values structure
  9. from sequence or rebuild sequence from values
  10. */
  11. var syncRatems = 10;
  12. var syncDelta = 0.;
  13. var doSync = false ;
  14. var debug = true;
  15. var debugFile;
  16. var parametersPath = local.parameters ;
  17. var sequence ;
  18. var sequencePath = local.parameters.sequence ;
  19. var file ;
  20. var filePath = local.parameters.sequenceFile ;
  21. var newGroupLayers = local.values.newGroup.layers ;
  22. var groups = local.values.groups ;
  23. var cues = local.getChild("values").keys.cues ;
  24. // var cuesList = []; //holds cues containers reference
  25. var layers = local.values.keys.layers ;
  26. var layerList = {}; //holds layer container as object with reference and an array of keys containers references
  27. var rebuildValues = script.addTrigger("rebuild values", "adds a key at current cursor position" );
  28. var refreshKeys = script.addTrigger("refresh keys", "truc");
  29. var printKeys = script.addTrigger("printKeys","truc");
  30. var clearSeq = script.addTrigger("clear Sequence","truc");
  31. var sequence_structure = { params: {},
  32. groups:{},
  33. keys:{
  34. cues:{},
  35. layers:{}
  36. }
  37. };
  38. //WAS tl_groups
  39. /*group0 : { inCue : {pan : "key", tilt : "key", zoom : "key", dim : "key", focus : "key"},
  40. outCue : {pan : "key", tilt : "key", zoom : "key", dim : "key", focus : "key"}
  41. }*/
  42. ///////////////////// SCRIPT FUNCTIONS //////////////////////////////
  43. function init() {
  44. script.log("LOADED SEQUENCE GROUPING MANAGEMENT MODULE ");
  45. //adapt update rate
  46. updateSyncRate();
  47. updateSynchronize();
  48. //test if a sequence is already choosen else refresh and unlock sequence enum
  49. sequence = sequencePath.getKey();
  50. if(sequence == ""){refreshSequenceEnum();}
  51. else{sequencePath.setAttribute("readonly", true);}
  52. }
  53. function scriptParameterChanged(param){
  54. if (param.is(printKeys) ){printKeys();}
  55. else if(param.is(rebuildValues)){struct_buildValuesFromSeq();}
  56. else if (param.is(refreshKeys)){
  57. script.log("refreshKeys");
  58. refreshKeysList();
  59. }
  60. else if (param.is(clearSeq)){seq_clearSequence();}
  61. else {script.log("scriptparamchanged" + param.name);}
  62. }
  63. function update(deltaTime){
  64. if(doSync){
  65. syncDelta += deltaTime ;
  66. // script.log(syncDelta);
  67. if (syncDelta >= syncRatems){
  68. syncDelta = 0. ;
  69. struct_buildValuesFromSeq();
  70. }
  71. }
  72. }
  73. /////////////////////////// HELPERS /////////////////////////////////
  74. function printMethodsAndProperties(obj){
  75. script.log(" ");
  76. var name = obj.getControlAddress() == undefined ? "object" : obj.getControlAddress();
  77. // var name = "object";
  78. script.log(" METHODS OF " + name);
  79. var methods = util.getObjectMethods(obj);
  80. for(var i=0 ; i<methods.length ; i++){
  81. script.log(" "+ methods[i]);
  82. }
  83. script.log(" PARAMETERS OF " + name);
  84. var props = util.getObjectProperties(obj, true, false);
  85. for(var i=0 ; i<props.length ; i++){
  86. script.log(" "+ props[i]);
  87. }
  88. script.log(" OBJECTS OF " + name);
  89. var props = util.getObjectProperties(obj, false, true);
  90. for(var i=0 ; i<props.length ; i++){
  91. script.log(" "+ props[i]);
  92. }
  93. }
  94. function printKeys(){
  95. var seq = root.sequences.sequence.layers.mapping.automation.getItems() ;
  96. if(seq.length){
  97. for(var i=0; i<seq.length; i++){
  98. script.log (">> "+seq[i].name + " " + seq[i].position.get() + " " + seq[i].listSize.get() );
  99. }
  100. }
  101. else{script.log("nothing to print");}
  102. }
  103. /////////////////////// PARAMETERS FUNCTIONS ///////////////////////
  104. // Module callback
  105. function moduleParameterChanged(param){
  106. if (param.is(parametersPath.importExport.sequenceFile)) {}
  107. else if (param.is(parametersPath.importExport.loadSequence)){importSequenceFile();}
  108. else if (param.is(parametersPath.importExport.exportSequence)) { exportSequenceFile();}
  109. else if (param.is(parametersPath.synchronize)){updateSynchronize();}
  110. else if (param.is(parametersPath.syncRate)){updateSyncRate();}
  111. else if (param.is(parametersPath.changeSequence)){refreshSequenceEnum();}
  112. else if (param.is(parametersPath.sequence)){
  113. sequence = sequencePath.getKey();
  114. script.log("watching "+ sequence);
  115. }
  116. else{script.log("received module param :" + param.name);}
  117. }
  118. function updateSynchronize(){
  119. doSync = parametersPath.synchronize.get();
  120. script.log(doSync ? "sync ON" : "sync OFF" );
  121. }
  122. function updateSyncRate(){
  123. syncRatems = parametersPath.syncRate.get() / 1000.;
  124. script.log("new sync rate : " + syncRatems);
  125. // script.setUpdateRate(syncRatems);
  126. }
  127. //refresh Enum
  128. function refreshSequenceEnum(){
  129. script.log("refresh list of sequences");
  130. local.parameters.sequence.setAttribute("readonly",false);
  131. if(root.sequences.getItems().length){
  132. local.parameters.sequence.removeOptions();
  133. for(var i=0 ; i<root.sequences.getItems().length ; i++ ){
  134. local.parameters.sequence.addOption(root.sequences.getItems()[i].name,i);
  135. }
  136. }
  137. }
  138. function testSequenceFile(){
  139. var file = local.parameters.sequenceFile;
  140. //test if a file is declared
  141. if( file.getAbsolutePath() != ""){
  142. script.log("testing file " + file.getAbsolutePath() );
  143. var data = file.readFile(true);
  144. // test if expected fields are absent
  145. if (data.groups == undefined){
  146. script.log("file structure not recognized");
  147. refreshSequenceEnum();
  148. }
  149. //if all is well, let's load in sequence_structure
  150. else {
  151. script.log("ready to import");
  152. return 1;
  153. // loadSequenceFile();
  154. }
  155. }
  156. else {
  157. script.log("no file to load");
  158. refreshSequenceEnum();
  159. return 0;
  160. }
  161. }
  162. function importSequenceFile(){
  163. script.log("loading file");
  164. sequence_structure = local.parameters.sequenceFile.readFile(true);
  165. //lock enum with curent sequence name
  166. var sequenceList = local.parameters.sequence;
  167. sequenceList.removeOptions();
  168. sequenceList.addOption(sequence_structure.params.sequence, 0);
  169. local.parameters.sequence.setAttribute("readonly",true);
  170. }
  171. function exportSequenceFile(){
  172. script.log("exporting file");
  173. local.parameters.sequenceFile.writeFile(JSON.stringify(sequence_structure), true);
  174. }
  175. /////////////////////// VALUES FUNCTIONS ///////////////////////
  176. /* Values hold all keys, presented in group containers
  177. a nogroup container shows keys that are not grouped
  178. */
  179. // Value callback
  180. function moduleValueChanged(value){
  181. if (value.name == "addGroup"){createNewGroup(sequence_structure.params.sequence);}
  182. }
  183. //rebuild container references lists reading values structure
  184. function struct_syncList(){
  185. }
  186. //check if sequence and structure lists are in sync (same cues, layers, and keys)
  187. function struct_checkSeqSync(){
  188. }
  189. //rebuild values.keys structure from sequence
  190. function struct_buildValuesFromSeq(){
  191. var tl_seq = root.sequences.getItemWithName(sequence);
  192. var tl_cues = tl_seq.cues.getItems();
  193. var tl_layers = tl_seq.layers.getItems();
  194. //clear and rebuild containers
  195. // local.values.removeContainer("keys");
  196. // keys = local.values.addContainer("keys");
  197. // cues = keys.addContainer("Cues");
  198. // layers = keys.addContainer("layers");
  199. //build cues
  200. cues = local.getChild("values").keys.cues ;
  201. var cuesList = util.getObjectProperties(cues, true, false);
  202. // script.log("cueList : " +cuesList.length);
  203. // script.log("tl List : " +tl_cues.length);
  204. if (cuesList.length != tl_cues.length){
  205. var delta = cuesList.length-tl_cues.length;
  206. var addRemove = delta > 0 ? false : true ; //0 to remove, 1 to add
  207. delta = Math.abs(delta);
  208. script.log("change "+ delta + (addRemove ? " up" : " down"));
  209. for(var i=0; i<delta; i++){
  210. // script.log(i);
  211. if(addRemove){
  212. var newCue = cues.addContainer("newCue"+i);
  213. newCue.addFloatParameter("time", "position in time", 0., 0.);
  214. newCue.setCollapsed(true);
  215. }
  216. else {
  217. script.log(util.getObjectProperties(cues, true, false)[0]);
  218. cues.removeContainer(util.getObjectProperties(cues, true, false)[0]);
  219. }
  220. // cuesList = ;
  221. }
  222. }
  223. //update values
  224. cues = local.getChild("values").keys.cues ;
  225. var cuesList = util.getObjectProperties(cues, true, false);
  226. if(tl_cues.length){
  227. for (var i=0; i<tl_cues.length; i++){
  228. var currentCue = cues.getChild(cuesList[i]);
  229. currentCue.setName(tl_cues[i].name);
  230. currentCue.time.set(tl_cues[i].time.get());
  231. }
  232. }
  233. //build layers
  234. //build keys in layers
  235. }
  236. function struct_exportToFile(){}
  237. function rebuildValuesStructure() {
  238. script.log("updating values structure");
  239. //empty current structure
  240. // local.values.removeAll();
  241. local.getChild("Values").removeContainer("newGroup");
  242. local.getChild("Values").removeContainer("groups");
  243. local.getChild("Values").removeContainer("ungrouped");
  244. //rebuild containers
  245. var ng_cont = local.values.addContainer("New group");
  246. var g_cont = local.values.addContainer("groups");
  247. var ug_cont = local.values.addContainer("ungrouped");
  248. // rebuild new group
  249. ng_cont.addTrigger("add group", "adds a new group at cursor time with below values");
  250. ng_cont.addFloatParameter("group time", "time position where the group will be created ", 0., 0.);
  251. var layer_cont = ng_cont.addContainer("layers values");
  252. var layers = util.getObjectProperties(sequence_structure.keys.layers) ;
  253. for (var i=0; i<layers.length; i++){
  254. //add a float value in each layer for group creation
  255. layer_cont.addFloatParameter(layers[i], "", 0., 0., 1.);
  256. ug_cont.addContainer(layers[i]);
  257. }
  258. //rebuild keys grouped/ungrouped
  259. //first create group containers in groups
  260. // //then create layer containers in ungrouped
  261. // var layer_cont = ug_cont.addContainer("layers values");
  262. }
  263. /////////////////////// TIMELINE FUNCTIONS ///////////////////////
  264. function seq_clearSequence(){
  265. var seq = root.sequences.getItemWithName(sequence) ;
  266. script.log("clearing all keys and cues of sequence : "+seq.name);
  267. seq.cues.removeAll();
  268. var layers = seq.layers.getItems();
  269. if(layers.length){
  270. for (var i = 0; i<layers.length; i++){
  271. layers[i].automation.removeAll();
  272. }
  273. }
  274. }
  275. //use Values structure to rebuild the sequence
  276. function seq_buildSeqFromValues(){}
  277. //use file to rebuild sequence
  278. function seq_buildSeqFromFile(){}
  279. function refreshKeysList(){
  280. var sequence = root.sequences.getItemWithName(sequence_structure.params.sequence);
  281. var cues = sequence.cues.getItems();
  282. sequence_structure.keys.cues = {};
  283. if(cues.length){
  284. for (var i = 0 ; i < cues.length ; i++){
  285. sequence_structure.keys.cues['cue'+i] = {index : i};
  286. sequence_structure.keys['cues']['cue'+i]['name'] = cues[i].name;
  287. sequence_structure.keys['cues']['cue'+i]['niceName'] = cues[i].niceName;
  288. sequence_structure.keys['cues']['cue'+i]['time'] = cues[i].time.get();
  289. // script.log(tl_keyframes['cues']['cue'+i].time);
  290. }
  291. }
  292. var layers = sequence.layers.getItems();
  293. sequence_structure.keys.layers={};
  294. if(layers.length){
  295. for (var i = 0 ; i < layers.length ; i++){
  296. sequence_structure['keys']['layers'][layers[i].name] = {};
  297. // script.log(currentLayer.name);
  298. if(layers[i].automation.getItems().length){
  299. // script.log(currentLayer.automation.items.length);
  300. for (var j = 0 ; j < layers[i].automation.getItems().length ; j++){
  301. var currentkey = layers[i].automation.getItems()[j] ;
  302. sequence_structure['keys']['layers'][layers[i].name][currentkey.name] = {
  303. position : currentkey.position.get(),
  304. value : currentkey.value.get(),
  305. name : currentkey.name,
  306. niceName : currentkey.niceName,
  307. //la propriete "group" est écrite
  308. group : currentkey.group
  309. // group : currentkey.hasChild("group") != undefined ? currentkey.group.get() : "ungrouped"
  310. };
  311. // script.log(tl_keyframes['keys'][currentLayer.name][currentkey.name].value);
  312. }
  313. }
  314. }
  315. }
  316. // myFile.writeFile(JSON.stringify(tl_keyframes), 1);
  317. }
  318. // function writeKeyGroup(){
  319. // var groups = sequence_structure.groups
  320. // }
  321. function createNewGroup(seqName){
  322. //create a cue and a key in each layer at cursor position in selected sequence
  323. var groupIndex = util.getObjectProperties(sequence_structure.groups) ;
  324. script.log(groupIndex.length);
  325. // printMethodsAndProperties(groupIndex);
  326. var seq = root.sequences.getItemWithName(seqName);
  327. var currentTime = seq.currentTime.get() ;
  328. // var currentTime = local.values.newGroup.groupTime.get();
  329. script.log(currentTime);
  330. newCue = seq.cues.addItem();
  331. newCue.time.set(currentTime);
  332. var layers = seq.layers.getItems();
  333. script.log(layers.length);
  334. // var struc_layers = util.getObjectProperties(sequence_structure.keys.layers);
  335. if(layers.length){
  336. for(var i=0;i<layers.length; i++ ){
  337. // script.log(sequence_structure.keys.layers[layers[i].name]);
  338. newKey = layers[i].automation.addItem();
  339. newKey.position.set(currentTime);
  340. script.log(local.values.newGroup.layersValues[layers[i].name].get());
  341. newKey.value.set(local.values.newGroup.layersValues[layers[i].name].get());
  342. newKey.addStringParameter("group", "key is part of this group","mongroupe");
  343. layers[i].automation.reorderItems();
  344. }
  345. }
  346. // seq = seq.getItems();
  347. }