Home Reference Source

cables_dev/cables_ui/src/ui/components/opparampanel/valuechanger.js

  1. import { ele } from "cables-shared-client";
  2. import { utils } from "cables";
  3. import { GuiText } from "../../text.js";
  4. import { hideToolTip } from "../../elements/tooltips.js";
  5. import undo from "../../utils/undo.js";
  6. import paramsHelper from "./params_helper.js";
  7. import { gui } from "../../gui.js";
  8. let pointerLockFirstTime = true;
  9. export default valueChanger;
  10. /**
  11. * mouse and keyboard interactions with port parameters
  12. */
  13. function valueChanger(eleId, focus, portName, opid)
  14. {
  15. gui.showInfo(GuiText.valueChangerInput);
  16. const eleInput = ele.byId(eleId);
  17. const eleContainer = ele.byId(eleId + "-container");
  18. const eleNumInputDisplay = document.querySelector("#" + eleId + "-container .numberinput-display");
  19. const theOp = gui.corePatch().getOpById(opid);
  20. if (!theOp) return;
  21. const thePort = theOp.getPort(portName);
  22. let isDown = false;
  23. const startVal = eleInputValue();
  24. let incMode = 0;
  25. let mouseDownTime = 0;
  26. let usePointerLock = true;
  27. if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) usePointerLock = false;
  28. document.addEventListener("pointerup", up);
  29. document.addEventListener("pointerdown", down);
  30. eleInput.addEventListener("focusout", blur);
  31. if (focus)
  32. {
  33. setTextEdit(true);
  34. eleInput.addEventListener("keydown", paramsHelper.inputListenerCursorKeys);
  35. // elem.keydown(paramsHelper.inputListenerCursorKeys);
  36. }
  37. function setTextEdit(enabled)
  38. {
  39. ele.forEachClass("numberinput", (elm) => { elm.classList.remove("numberinputFocussed"); });
  40. if (enabled)
  41. {
  42. if (eleContainer.classList.contains("valuesliderinput"))
  43. eleInput.addEventListener("input", () => { paramsHelper.valueChangerSetSliderCSS(eleInput.value, eleContainer); });
  44. ele.hide(eleNumInputDisplay);
  45. eleContainer.classList.add("numberinputFocussed");
  46. ele.show(eleInput);
  47. eleInput.focus();
  48. const vv = eleInput.value;
  49. eleInput.setSelectionRange(0, vv.length);
  50. }
  51. else
  52. {
  53. if (eleContainer.classList.contains("valuesliderinput")) eleInput.addEventListener("input",
  54. () =>
  55. {
  56. paramsHelper.valueChangerSetSliderCSS(eleInput.value, eleContainer);
  57. });
  58. ele.show(eleNumInputDisplay);
  59. ele.hide(eleInput);
  60. eleInput.blur();
  61. document.removeEventListener("pointerup", up);
  62. document.removeEventListener("pointerdown", down);
  63. }
  64. }
  65. function down(e)
  66. {
  67. if (ele.hasFocus(eleInput)) return;
  68. eleInput.removeEventListener("wheel", paramsHelper.inputListenerMousewheel);
  69. eleInput.addEventListener("wheel", paramsHelper.inputListenerMousewheel);
  70. eleInput.addEventListener("keydown", paramsHelper.inputListenerCursorKeys);
  71. mouseDownTime = performance.now();
  72. isDown = true;
  73. if (usePointerLock)
  74. {
  75. document.addEventListener("pointerlockerror", lockError);
  76. document.addEventListener("pointerlockchange", lockChange);
  77. document.addEventListener("mozpointerlockchange", lockChange);
  78. document.addEventListener("webkitpointerlockchange", lockChange);
  79. if (eleInput.classList.contains("inc_int")) incMode = 1;
  80. eleInput.requestPointerLock = eleInput.requestPointerLock || eleInput.mozRequestPointerLock || eleInput.webkitRequestPointerLock;
  81. if (eleInput.requestPointerLock) eleInput.requestPointerLock();
  82. }
  83. else
  84. {
  85. document.addEventListener("pointermove", move);
  86. }
  87. CABLES.mouseDraggingValue = true;
  88. }
  89. function up(e)
  90. {
  91. if (ele.hasFocus(eleInput)) return;
  92. CABLES.mouseDraggingValue = false;
  93. if (opid && portName)
  94. {
  95. const undofunc = (function (_portName, opId, oldVal, newVal)
  96. {
  97. if (oldVal != newVal)
  98. undo.add({
  99. "title": "Value mousedrag " + oldVal + " to " + newVal,
  100. undo()
  101. {
  102. const op = gui.corePatch().getOpById(opid);
  103. const p = op.getPort(_portName);
  104. gui.patchView.showDefaultPanel();
  105. p.set(oldVal);
  106. gui.opParams.show(op);
  107. gui.patchView.focusOp(null);
  108. gui.patchView.focusOp(op.id);
  109. gui.patchView.centerSelectOp(op.id);
  110. },
  111. redo()
  112. {
  113. const op = gui.corePatch().getOpById(opid);
  114. const p = op.getPort(_portName);
  115. gui.patchView.showDefaultPanel();
  116. p.set(newVal);
  117. gui.opParams.show(op);
  118. gui.patchView.focusOp(null);
  119. gui.patchView.focusOp(op.id);
  120. gui.patchView.centerSelectOp(op.id);
  121. }
  122. });
  123. }(portName, opid, parseFloat(startVal), parseFloat(eleInput.value)));
  124. }
  125. // gui.setStateUnsaved();
  126. gui.savedState.setUnSaved("valuechangerUp", thePort.op.getSubPatch());
  127. isDown = false;
  128. if (usePointerLock)
  129. {
  130. document.removeEventListener("pointerlockerror", lockError, false);
  131. document.removeEventListener("pointerlockchange", lockChange, false);
  132. document.removeEventListener("mozpointerlockchange", lockChange, false);
  133. document.removeEventListener("webkitpointerlockchange", lockChange, false);
  134. if (document.exitPointerLock)document.exitPointerLock();
  135. }
  136. document.removeEventListener("pointerup", up);
  137. document.removeEventListener("pointerdown", down);
  138. document.removeEventListener("pointermove", move, false);
  139. if (performance.now() - mouseDownTime < 200) setTextEdit(true);
  140. }
  141. function setProgress(v)
  142. {
  143. paramsHelper.valueChangerSetSliderCSS(eleInput.value, eleContainer);
  144. return v;
  145. }
  146. function eleInputValue()
  147. {
  148. eleInput.value = eleInput.value.replaceAll(",", ".");
  149. let str = eleInput.value;
  150. let v = parseFloat(str);
  151. if (v != v)v = 0;
  152. return v;
  153. }
  154. function move(e)
  155. {
  156. if (pointerLockFirstTime)
  157. {
  158. pointerLockFirstTime = false;
  159. return;
  160. }
  161. if (ele.hasFocus(eleInput)) return;
  162. // gui.setStateUnsaved();
  163. gui.savedState.setUnSaved("valuechangerMove", thePort.op.getSubPatch());
  164. let v = eleInputValue();
  165. let inc = 0;
  166. if (thePort.uiAttribs.min != undefined)
  167. v = utils.map(v, thePort.uiAttribs.min, thePort.uiAttribs.max, 0, 1);
  168. if (Math.abs(e.movementX) > 5) mouseDownTime = 0;
  169. if (eleContainer.classList.contains("valuesliderinput"))
  170. {
  171. inc = e.movementX * 0.001;
  172. v += inc;
  173. v = Math.max(0, v);
  174. v = Math.min(1, v);
  175. v = Math.round(v * 1000) / 1000;
  176. v = setProgress(v);
  177. }
  178. else
  179. if (incMode == 0)
  180. {
  181. inc = e.movementX * 0.01;
  182. if (e.shiftKey || e.which == 3)inc = e.movementX * 0.5;
  183. v += inc;
  184. v = Math.round(v * 1000) / 1000;
  185. }
  186. else
  187. {
  188. inc = e.movementX * 1;
  189. if (e.shiftKey || e.which == 3)inc = e.movementX * 5;
  190. v += inc;
  191. v = Math.floor(v);
  192. }
  193. if (thePort.uiAttribs.min != undefined)
  194. v = utils.map(v, 0, 1, thePort.uiAttribs.min, thePort.uiAttribs.max);
  195. eleInput.value = v;
  196. eleNumInputDisplay.innerHTML = v;
  197. eleInput.dispatchEvent(new Event("input"));
  198. }
  199. function lockError(e)
  200. {
  201. // console.log("pointer lock error...", e);
  202. }
  203. function lockChange(e)
  204. {
  205. if (document.pointerLockElement === eleInput || document.mozPointerLockElement === eleInput || document.webkitPointerLockElement === eleInput)
  206. {
  207. pointerLockFirstTime = true;
  208. document.addEventListener("pointermove", move);
  209. }
  210. else
  211. {
  212. // propably cancled by escape key / reset value
  213. eleInput.value = startVal;
  214. eleNumInputDisplay.innerHTML = startVal;
  215. eleInput.dispatchEvent(new Event("input"));
  216. up();
  217. }
  218. }
  219. function blur(e)
  220. {
  221. // value changed after blur
  222. if (startVal != eleInputValue())
  223. {
  224. if (opid && portName)
  225. {
  226. if (isNaN(eleInput.value))
  227. {
  228. const op = gui.corePatch().getOpById(opid);
  229. const p = op.getPort(portName);
  230. let mathParsed = eleInput.value;
  231. mathParsed = mathParsed.replaceAll(",", ".");
  232. try
  233. {
  234. mathParsed = CABLES.UI.mathparser.parse(eleInput.value);
  235. }
  236. catch (ex)
  237. {
  238. // failed to parse math, use unparsed value
  239. mathParsed = eleInputValue();
  240. }
  241. eleInput.value = mathParsed;
  242. p.set(mathParsed);
  243. hideToolTip();
  244. }
  245. }
  246. }
  247. hideToolTip();
  248. eleInput.removeEventListener("focusout", blur);
  249. eleNumInputDisplay.innerHTML = eleInput.value;
  250. setTextEdit(false);
  251. if (eleInput.classList.contains("valuesliderinput"))setProgress();
  252. }
  253. }