keyframes.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. //MIDI 14bit management
  2. var pan_midi_ch = script.addIntParameter("pan midi channel", "", 0);
  3. var pan_midi={channel:pan_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.pan.pan };
  4. var tilt_midi_ch = script.addIntParameter("tilt midi channel", "", 1);
  5. var tilt_midi={channel:tilt_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.tilt.tilt};
  6. var delCue_Trigger = script.addTrigger("clear cues", "clear all cues in the timeline");
  7. var clearTL_Trigger = script.addTrigger("clear timeline", "clear all cues and keys in the timeline");
  8. var createKeyGroup_Trigger = script.addTrigger("create group","create key group @ current time");
  9. var createKeyGroupInOut_Trigger = script.addTrigger("create InOut group","create key group @ current time and key group ten seconds later, with constant values inbetween");
  10. var myFile = script.addFileParameter("textFile", "this is a text file");
  11. var myTrigger = script.addTrigger("Print pan keys", "Trigger description");
  12. var myTrigger2 = script.addTrigger("test", "Trigger description");
  13. //This will add a trigger (button)
  14. var tl_keyframes = {cues : {}, keys : {}} ; //holds timeline keys, is updated at fixed rate
  15. //variable to hold group logic
  16. var tl_groups = {groups: 0
  17. /*group0 : { inCue : {pan : "key", tilt : "key", zoom : "key", dim : "key", focus : "key"},
  18. outCue : {pan : "key", tilt : "key", zoom : "key", dim : "key", focus : "key"}
  19. }*/
  20. } ;
  21. var file_keyframes = {groups : 0} ; //holds file keys, used to save and load
  22. var myFloatParam = script.addFloatParameter("My Float Param","Description of my float param",.1,0,1);
  23. /*
  24. var myBoolParam = script.addBoolParameter("My Bool Param","Description of my bool param",false); //This will add a boolean parameter (toggle), defaut unchecked
  25. var myFloatParam = script.addFloatParameter("My Float Param","Description of my float param",.1,0,1); //This will add a float number parameter (slider), default value of 0.1, with a range between 0 and 1
  26. var myIntParam = script.addIntParameter("My Int Param","Description of my int param",2,0,10); //This will add an integer number parameter (stepper), default value of 2, with a range between 0 and 10
  27. var myStringParam = script.addStringParameter("My String Param","Description of my string param", "cool"); //This will add a string parameter (text field), default value is "cool"
  28. var myColorParam = script.addColorParameter("My Color Param","Description of my color param",0xff0000ff); //This will add a color parameter (color picker), default value of opaque blue (ARGB)
  29. var myP2DParam = script.addPoint2DParameter("My P2D Param","Description of my p2d param"); //This will add a point 2d parameter
  30. var myP3DParam = script.addPoint3DParameter("My P3D Param","Description of my p3d param"); //This will add a point 3d parameter
  31. var myTargetParam = script.addTargetParameter("My Target Param","Description of my target param"); //This will add a target parameter (to reference another parameter)
  32. var myEnumParam = script.addEnumParameter("My Enum Param","Description of my enum param", //This will add a enum parameter (dropdown with options)
  33. "Option 1", 1, //Each pair of values after the first 2 arguments define an option and its linked data
  34. "Option 2", 5, //First argument of an option is the label (string)
  35. "Option 3", "banana" //Second argument is the value, it can be whatever you want
  36. );
  37. */
  38. //you can also declare custom internal variable
  39. //var myValue = 5;
  40. /////////////////////// MIDI FUNCTIONS ///////////////////////
  41. function checkAxe(CC){
  42. if(CC==pan_midi.channel || CC==pan_midi.channel+32){
  43. return pan_midi;
  44. }
  45. else return 0;
  46. }
  47. function updateAxe(axe, CC, value){
  48. if(CC==axe.channel){
  49. axe.MSB = value;
  50. // root.customVariables.unitValues.variables.pan.pan.set((128*axe.MSB+axe.LSB)/16383.0);
  51. }
  52. if(CC==axe.channel+32){
  53. axe.LSB = value;
  54. // myFloatParam.set((128*MSB+LSB)/16383.0);
  55. }
  56. axe.target=(128*axe.MSB+axe.LSB)/16383.0;
  57. script.log(axe.target);
  58. }
  59. /////////////////////// TIMELINE FUNCTIONS ///////////////////////
  60. function refresh_tl_keys_list(){
  61. // tl_keyframes['cues']
  62. if(root.sequences.keys.cues.getItems().length){
  63. for (var i = 0 ; i < root.sequences.keys.cues.getItems().length ; i++){
  64. tl_keyframes['cues']['cue'+i] = {index : i};
  65. tl_keyframes['cues']['cue'+i]['name'] = root.sequences.keys.cues.getItems()[i].name;
  66. tl_keyframes['cues']['cue'+i]['time'] = root.sequences.keys.cues.getItems()[i].time.get();
  67. // script.log(tl_keyframes['cues']['cue'+i].time);
  68. }
  69. }
  70. if(root.sequences.keys.layers.getItems().length){
  71. for (var i = 0 ; i < root.sequences.keys.layers.getItems().length ; i++){
  72. var currentLayer = root.sequences.keys.layers.getItems()[i] ;
  73. tl_keyframes['keys'][currentLayer.name] = {};
  74. // script.log(currentLayer.name);
  75. if(currentLayer.automation.getItems().length){
  76. // script.log(currentLayer.automation.items.length);
  77. for (var j = 0 ; j < currentLayer.automation.getItems().length ; j++){
  78. var currentkey = currentLayer.automation.getItems()[j] ;
  79. tl_keyframes['keys'][currentLayer.name][currentkey.name] = {
  80. position : currentkey.position.get(),
  81. value : currentkey.value.get()
  82. };
  83. // script.log(tl_keyframes['keys'][currentLayer.name][currentkey.name].value);
  84. }
  85. }
  86. }
  87. }
  88. // myFile.writeFile(JSON.stringify(tl_keyframes), 1);
  89. }
  90. function reorderLayers(){
  91. root.sequences.keys.layers.pan.automation.reorderItems();
  92. // if(root.sequences.keys.layers.getItems().length){
  93. // for (var i = 0 ; i < root.sequences.keys.layers.getItems().length ; i++){
  94. // root.sequences.keys.layers.getItems()[i].automation.reorderItems();
  95. // }
  96. // }
  97. }
  98. function apply_tl_groups() {
  99. if(tl_groups.groups){
  100. for(var i=0 ; i<tl_groups.groups ; i++){
  101. //set all keys in a group to its cue time
  102. var tempGroup = tl_groups['group'+i];
  103. var hasOut= typeof tempGroup.cueOut.pan!='undefined' ;
  104. var layers = root.sequences.keys.layers.getItems() ;
  105. var inTime = root.sequences.keys.cues[tempGroup.cueIn.cue].time.get();
  106. var outTime;
  107. if(hasOut){ outTime = root.sequences.keys.cues[tempGroup.cueOut.cue].time.get();}
  108. if(layers.length){
  109. for(var j = 0 ; j<layers.length ; j++){
  110. var tempLayer=layers[j].name;
  111. var inKey = tempGroup.cueIn[tempLayer];
  112. root.sequences.keys.layers[tempLayer].automation[inKey].position.set(inTime);
  113. if (hasOut) {
  114. var outKey = tempGroup.cueOut[tempLayer];
  115. root.sequences.keys.layers[tempLayer].automation[outKey].position.set(outTime);
  116. //apply inKey value
  117. root.sequences.keys.layers[tempLayer].automation[outKey].value.set(root.sequences.keys.layers[tempLayer].automation[inKey].value.get());
  118. }
  119. }
  120. }
  121. }
  122. }
  123. // root.sequences.keys.layers.items[0].automation.items[0].position.set(root.sequences.keys.cues.items[0].time.get());
  124. // script.log(root.sequences.keys.cues.items[0].name + " " + root.sequences.keys.layers.items[0].automation.items[0].name );
  125. }
  126. function clear_tl_cues(){
  127. if(root.sequences.keys.cues.getItems().length){
  128. for (var i = root.sequences.keys.cues.getItems().length-1 ; i>=0 ; i--){
  129. root.sequences.keys.cues.removeItem(root.sequences.keys.cues.getItems()[i].name);
  130. }
  131. script.log("Cleared all cues");
  132. }
  133. else {script.log("no cues to clear");}
  134. }
  135. function clear_tl_keys(){
  136. script.log(root.sequences.keys.layers.getItems().length);
  137. if(root.sequences.keys.layers.getItems().length){
  138. for (var i = root.sequences.keys.layers.getItems().length-1 ; i >=0 ; i--){
  139. if(root.sequences.keys.layers.getItems()[i].automation.getItems().length){
  140. for (var j = root.sequences.keys.layers.getItems()[i].automation.getItems().length-1 ; j >= 0 ; j--){
  141. root.sequences.keys.layers.getItems()[i].automation.removeItem(root.sequences.keys.layers.getItems()[i].automation.getItems()[j].name);
  142. }
  143. }
  144. // root.sequences.keys.cues.removeItem(root.sequences.keys.cues.items[i].name);
  145. }
  146. script.log("Cleared all keys");
  147. }
  148. else{script.log("no keys to clear");}
  149. }
  150. function clear_tl_full(){
  151. clear_tl_cues();
  152. clear_tl_keys();
  153. tl_groups = {groups: 0};
  154. myFile.writeFile(JSON.stringify(tl_groups), 1);
  155. }
  156. function create_keyGroup(mode){ //mode=0 single cue, mode=1 dual cues
  157. //get current variables values
  158. var tempValues = {
  159. position: root.sequences.keys.currentTime.get() ,
  160. pan : root.customVariables.unitValues.variables.pan.pan.get(),
  161. tilt : root.customVariables.unitValues.variables.tilt.tilt.get(),
  162. zoom : root.customVariables.unitValues.variables.zoom.zoom.get(),
  163. dim : root.customVariables.unitValues.variables.dimmer.dimmer.get(),
  164. focus: root.customVariables.unitValues.variables.focus.focus.get(),
  165. speed : root.customVariables.unitValues.variables.speed.speed.get(),
  166. };
  167. // script.log(tempValues.pan);
  168. //create new entry in group list
  169. var groupIndex = tl_groups.groups;
  170. script.log("creating group # : " + groupIndex);
  171. tl_groups['group'+groupIndex] ={cueIn: {}};
  172. var inCue = root.sequences.keys.cues.addItem();
  173. inCue.time.set(tempValues.position);
  174. tl_groups['group'+groupIndex].cueIn.cue = inCue.name;
  175. //create cues and tl_group entries
  176. if(mode){
  177. tl_groups['group'+groupIndex].cueOut = {} ;
  178. var outCue = root.sequences.keys.cues.addItem();
  179. outCue.time.set(tempValues.position+10.);
  180. tl_groups['group'+groupIndex].cueOut.cue = outCue.name;
  181. }
  182. //create keys
  183. var layers = root.sequences.keys.layers.getItems() ;
  184. if(layers.length){
  185. for(var i = 0 ; i<layers.length ; i++){
  186. tempKeyIn = root.sequences.keys.layers.getItems()[i].automation.addItem();
  187. tempKeyIn.value.set(tempValues[root.sequences.keys.layers.getItems()[i].name]);
  188. tempKeyIn.position.set(inCue.time.get());
  189. tl_groups['group'+groupIndex].cueIn[root.sequences.keys.layers.getItems()[i].name]=tempKeyIn.name;
  190. if(mode) {
  191. tempKeyOut = root.sequences.keys.layers.getItems()[i].automation.addItem();
  192. tempKeyOut.value.set(tempValues[root.sequences.keys.layers.getItems()[i].name]);
  193. tempKeyOut.position.set(outCue.time.get());
  194. tl_groups['group'+groupIndex].cueOut[root.sequences.keys.layers.getItems()[i].name]=tempKeyOut.name;
  195. }
  196. root.sequences.keys.layers.getItems()[i].automation.reorderItems();
  197. }
  198. }
  199. tl_groups.groups += 1;
  200. myFile.writeFile(JSON.stringify(tl_groups), 1);
  201. }
  202. /////////////////////// SCRIPT FUNCTIONS ///////////////////////
  203. /*
  204. The init() function will allow you to init everything you want after the script has been checked and loaded
  205. WARNING it also means that if you change values of your parameters by hand and set their values inside the init() function, they will be reset to this value each time the script is reloaded !
  206. */
  207. function init()
  208. {
  209. script.log("Reading key group file");
  210. tl_groups = JSON.parse(myFile.readFile());
  211. //script.log (tl_groups.groups);
  212. script.log(root.sequences.keys.layers.pan.automation.getItems()[0]);
  213. //root.sequences.keys.layers.pan.value
  214. // script.log(root.reference);
  215. // script.log(root.sequences.keys.addCueAt(1.11));
  216. // root.sequences.keys.layers[0].getObjectProperties();
  217. //myFloatParam.set(5); //The .set() function set the parameter to this value.
  218. //myColorParam.set([1,.5,1,1]); //for a color parameter, you need to pass an array with 3 (RGB) or 4 (RGBA) values.
  219. //myP2DParam.set([1.5,-5]); // for a Point2D parameter, you need to pass 2 values (XY)
  220. //myP3DParam.set([1.5,2,-3]); // for a Point3D parameter, you need to pass 3 values (XYZ)
  221. // tl.cues.cue.time
  222. // script.log(tl.cues.items[0].name);
  223. // for (var i = tl.cues.items.length-1 ; i>=0 ; i--){
  224. // // tl.cues.items[i].name='truc'+i;
  225. // script.log(tl.cues.items[i].time.get());
  226. // }
  227. root.sequences.keys.cues.getItems()[0].setName("moncue");
  228. // root.sequences.keys.cues.cue.time
  229. }
  230. /*
  231. This function will be called each time a parameter of your script has changed
  232. */
  233. function scriptParameterChanged(param)
  234. {
  235. if(param.is(myTrigger)){
  236. script.log(root.sequences.keys.layers.getItems()[0].automation.getItems().length);
  237. for (var j = 0 ; j<root.sequences.keys.layers.getItems()[0].automation.getItems().length ; j++){
  238. script.log(root.sequences.keys.layers.getItems()[0].automation.getItems()[j].name);
  239. }
  240. // for (var i = tl.cues.items.length-1 ; i>=0 ; i--){
  241. // script.log(tl.cues.items[i].name);
  242. // }
  243. // myFile.writeFile(JSON.stringify(testJSON), 1);
  244. }
  245. else if(param.is(myTrigger2)){
  246. // var props = util.getObjectMethods(root.sequences.keys.layers.getItems()[0].automation, true, true);
  247. // for (var j = 0 ; j<props.length ; j++){
  248. // script.log(props[i].name);
  249. // }
  250. reorderLayers();
  251. script.log("reorder");
  252. }
  253. else if (param.is(delCue_Trigger)){clear_tl_cues();}
  254. else if (param.is(clearTL_Trigger)){clear_tl_full();}
  255. else if (param.is(createKeyGroup_Trigger)){create_keyGroup(0);}
  256. else if (param.is(createKeyGroupInOut_Trigger)){create_keyGroup(1);}
  257. else if (param.is(myFloatParam)){
  258. //var time = myFloatParam.get() * root.sequences.keys.totalTime.get();
  259. // root.sequences.keys.layers.items[0].automation.items[0].position.set(time);
  260. }
  261. else if(param.is(myEnumParam)) script.log("Label = "+param.get()+", data = "+param.getData()); //The enum parameter has a special function getData() to get the data associated to the option
  262. // else script.log("Value is "+param.get()); //All parameters have a get() method that will return their value
  263. // script.log(myFile.readFile());
  264. }
  265. /*
  266. This function, if you declare it, will launch a timer at 50hz, calling this method on each tick
  267. */
  268. var tl_refresh_delta = 0.;
  269. var tl_refresh_rate = 0.1;
  270. function update(deltaTime)
  271. {
  272. tl_refresh_delta += deltaTime ;
  273. if (tl_refresh_delta > tl_refresh_rate){
  274. tl_refresh_delta = 0. ;
  275. refresh_tl_keys_list();
  276. apply_tl_groups();
  277. //reorderLayers();
  278. // script.log("Update : "+util.getTime()+", delta = "+deltaTime); //deltaTime is the time between now and last update() call, util.getTime() will give you a timestamp relative to either the launch time of the software, or the start of the computer.
  279. }
  280. }
  281. /* ********** MODULE SPECIFIC SCRIPTING **********************
  282. The "local" variable refers to the object containing the scripts. In this case, the local variable refers to the module.
  283. It means that you can access any control inside this module by accessing it through its address.
  284. For instance, if the module has a float value named "Density", you can access it via local.values.density
  285. Then you can retrieve its value using local.values.density.get() and change its value using local.values.density.set()
  286. */
  287. /*
  288. This function will be called each time a parameter of this module has changed, meaning a parameter or trigger inside the "Parameters" panel of this module
  289. This function only exists because the script is in a module
  290. */
  291. function moduleParameterChanged(param)
  292. {
  293. // if(param.isParameter())
  294. // {
  295. // script.log("Module parameter changed : "+param.name+" > "+param.get());
  296. // }else
  297. // {
  298. // script.log("Module parameter triggered : "+value.name);
  299. // }
  300. }
  301. /*
  302. This function will be called each time a value of this module has changed, meaning a parameter or trigger inside the "Values" panel of this module
  303. This function only exists because the script is in a module
  304. */
  305. function moduleValueChanged(value)
  306. {
  307. // if(value.isParameter())
  308. // {
  309. // script.log("Module value changed : "+value.name+" > "+value.get());
  310. // }else
  311. // {
  312. // script.log("Module value triggered : "+value.name);
  313. // }
  314. }
  315. /* ********** MIDI MODULE SPECIFIC SCRIPTING ********************* */
  316. function ccEvent(channel, number, value)
  317. {
  318. // script.log("ControlChange received "+channel+", "+number+", "+value);
  319. //feedback to BCF
  320. local.sendCC(channel, number, value);
  321. var currentAxe=checkAxe(number);
  322. if (currentAxe){updateAxe(currentAxe, number, value);}
  323. // if(number==pan_midi.channel){
  324. // MSB = value;
  325. // myFloatParam.set((128*MSB+LSB)/16383.0);
  326. // }
  327. // if(number==32){
  328. // LSB = value;
  329. // myFloatParam.set((128*MSB+LSB)/16383.0);
  330. // }
  331. }