You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

535 lines
16KB

  1. #include "mscHack.hpp"
  2. #include "window.hpp"
  3. //-----------------------------------------------------
  4. // Procedure: constructor
  5. //-----------------------------------------------------
  6. Widget_EnvelopeEdit::Widget_EnvelopeEdit( int x, int y, int w, int h, int handleSize, void *pClass, EnvelopeEditCALLBACK *pCallback, int nchannels )
  7. {
  8. int ch, hd;
  9. if( !pClass || !pCallback )
  10. return;
  11. m_pClass = pClass;
  12. m_pCallback = pCallback;
  13. m_handleSize = handleSize;
  14. m_MaxChannels = nchannels;
  15. box.pos = Vec( x, y );
  16. box.size = Vec( w, h );
  17. // calc division size (16 divisions, 4 beats x 4 quarter)
  18. m_divw = ( ( (float)w - (float)ENVELOPE_HANDLES) / (float)ENVELOPE_DIVISIONS ) + 1.0f;
  19. m_handleSizeD2 = ( (float)handleSize / 2.0f );
  20. // handles
  21. for( ch = 0; ch < MAX_ENVELOPE_CHANNELS; ch++ )
  22. {
  23. m_EnvData[ ch ].Init( EnvelopeData::MODE_LOOP, EnvelopeData::RANGE_0to5, false, m_divw );
  24. for( hd = 0; hd < ENVELOPE_HANDLES; hd++ )
  25. m_HandleCol[ hd ].dwCol = 0xFFFFFF;
  26. }
  27. recalcLine( -1, 0 );
  28. m_BeatLen = (int)engineGetSampleRate();
  29. m_bInitialized = true;
  30. }
  31. //-----------------------------------------------------
  32. // Procedure: Val2y
  33. //-----------------------------------------------------
  34. float Widget_EnvelopeEdit::Val2y( float fval )
  35. {
  36. return clamp( box.size.y - ( fval * box.size.y ), 0.0f, box.size.y );
  37. }
  38. //-----------------------------------------------------
  39. // Procedure: y2Val
  40. //-----------------------------------------------------
  41. float Widget_EnvelopeEdit::y2Val( float fy )
  42. {
  43. return clamp( 1.0 - (fy / box.size.y ), 0.0f, 1.0f );
  44. }
  45. //-----------------------------------------------------
  46. // Procedure: recalcLine
  47. //-----------------------------------------------------
  48. void Widget_EnvelopeEdit::recalcLine( int chin, int handle )
  49. {
  50. // calc all lines
  51. if( chin == -1 )
  52. {
  53. for( int ch = 0; ch < MAX_ENVELOPE_CHANNELS; ch++ )
  54. {
  55. m_EnvData[ ch ].recalcLine( -1 );
  56. }
  57. }
  58. // calc line before and line after handle
  59. else
  60. {
  61. m_EnvData[ chin ].recalcLine( handle );
  62. }
  63. }
  64. //-----------------------------------------------------
  65. // Procedure: setPos
  66. //-----------------------------------------------------
  67. void Widget_EnvelopeEdit::setView( int ch )
  68. {
  69. if( !m_bInitialized && ch < MAX_ENVELOPE_CHANNELS && ch >= 0 )
  70. return;
  71. m_currentChannel = ch;
  72. }
  73. //-----------------------------------------------------
  74. // Procedure: resetVal
  75. //-----------------------------------------------------
  76. void Widget_EnvelopeEdit::resetValAll( int ch, float val )
  77. {
  78. if( !m_bInitialized && ch < MAX_ENVELOPE_CHANNELS && ch >= 0 )
  79. return;
  80. m_EnvData[ ch ].resetValAll( val );
  81. }
  82. //-----------------------------------------------------
  83. // Procedure: setVal
  84. //-----------------------------------------------------
  85. void Widget_EnvelopeEdit::setVal( int ch, int handle, float val )
  86. {
  87. if( !m_bInitialized && ch < MAX_ENVELOPE_CHANNELS && ch >= 0 )
  88. return;
  89. m_EnvData[ ch ].setVal( handle, val );
  90. }
  91. //-----------------------------------------------------
  92. // Procedure: setRange
  93. //-----------------------------------------------------
  94. void Widget_EnvelopeEdit::setRange( int ch, int Range )
  95. {
  96. if( !m_bInitialized && ch < MAX_ENVELOPE_CHANNELS && ch >= 0 )
  97. return;
  98. m_EnvData[ ch ].m_Range = Range;
  99. }
  100. //-----------------------------------------------------
  101. // Procedure: setMode
  102. //-----------------------------------------------------
  103. void Widget_EnvelopeEdit::setMode( int ch, int Mode )
  104. {
  105. if( !m_bInitialized && ch < MAX_ENVELOPE_CHANNELS && ch >= 0 )
  106. return;
  107. m_EnvData[ ch ].setMode( Mode );
  108. }
  109. //-----------------------------------------------------
  110. // Procedure: setGateMode
  111. //-----------------------------------------------------
  112. void Widget_EnvelopeEdit::setGateMode( int ch, bool bGate )
  113. {
  114. if( !m_bInitialized && ch < MAX_ENVELOPE_CHANNELS && ch >= 0 )
  115. return;
  116. m_EnvData[ ch ].m_bGateMode = bGate;
  117. }
  118. //-----------------------------------------------------
  119. // Procedure: setTimeDiv
  120. //-----------------------------------------------------
  121. void Widget_EnvelopeEdit::setTimeDiv( int ch, int timediv )
  122. {
  123. if( !m_bInitialized && ch < MAX_ENVELOPE_CHANNELS && ch >= 0 )
  124. return;
  125. m_TimeDiv[ ch ] = timediv;
  126. setBeatLen( m_BeatLen );
  127. }
  128. //-----------------------------------------------------
  129. // Procedure: setDataAll
  130. //-----------------------------------------------------
  131. int Widget_EnvelopeEdit::getPos( int ch )
  132. {
  133. return (int)( m_EnvData[ ch ].m_Clock.fpos * 10000.0f );
  134. }
  135. //-----------------------------------------------------
  136. // Procedure: setDataAll
  137. //-----------------------------------------------------
  138. void Widget_EnvelopeEdit::setPos( int ch, int pos )
  139. {
  140. m_EnvData[ ch ].m_Clock.fpos = (float)pos / 10000.0f;
  141. }
  142. //-----------------------------------------------------
  143. // Procedure: setDataAll
  144. //-----------------------------------------------------
  145. void Widget_EnvelopeEdit::setDataAll( int *pint )
  146. {
  147. int i, j, count = 0;
  148. if( !m_bInitialized )
  149. return;
  150. for( i = 0; i < MAX_ENVELOPE_CHANNELS; i++ )
  151. {
  152. for( j = 0; j < ENVELOPE_HANDLES; j++ )
  153. {
  154. m_EnvData[ i ].m_HandleVal[ j ] = clamp( (float)pint[ count++ ] / 10000.0f, 0.0f, 1.0f );
  155. }
  156. }
  157. // recalc all lines
  158. recalcLine( -1, 0 );
  159. }
  160. //-----------------------------------------------------
  161. // Procedure: getDataAll
  162. //-----------------------------------------------------
  163. void Widget_EnvelopeEdit::getDataAll( int *pint )
  164. {
  165. int i, j, count = 0;
  166. if( !m_bInitialized )
  167. return;
  168. for( i = 0; i < MAX_ENVELOPE_CHANNELS; i++ )
  169. {
  170. for( j = 0; j < ENVELOPE_HANDLES; j++ )
  171. {
  172. pint[ count++ ] = (int)( m_EnvData[ i ].m_HandleVal[ j ] * 10000.0 );
  173. }
  174. }
  175. }
  176. //-----------------------------------------------------
  177. // Procedure: draw
  178. //-----------------------------------------------------
  179. int hdivs[ EnvelopeData::nRANGES ] = { 6, 11, 11, 21, 2, 13 };
  180. void Widget_EnvelopeEdit::draw( NVGcontext *vg )
  181. {
  182. int h, hlines;
  183. float x, y, divsize;
  184. float linewidth = 1.0;
  185. if( !m_bInitialized )
  186. return;
  187. // fill bg
  188. nvgBeginPath(vg);
  189. nvgRect(vg, 0, 0, box.size.x-1, box.size.y-1 );
  190. //nvgFillColor(vg, nvgRGBA(40,40,40,255));
  191. nvgFillColor(vg, nvgRGBA(57, 10, 10,255));
  192. nvgFill(vg);
  193. nvgStrokeWidth( vg, linewidth );
  194. nvgStrokeColor( vg, nvgRGBA( 60, 60, 60, 255 ) );
  195. // draw bounding line
  196. /*nvgBeginPath( vg );
  197. nvgMoveTo( vg, 0, 0 );
  198. nvgLineTo( vg, box.size.x - 1, 0 );
  199. nvgLineTo( vg, box.size.x - 1, box.size.y - 1 );
  200. nvgLineTo( vg, 0, box.size.y - 1 );
  201. nvgClosePath( vg );
  202. nvgStroke( vg );*/
  203. x = 0.0;
  204. // draw vertical lines
  205. for( h = 0; h < ENVELOPE_HANDLES; h++ )
  206. {
  207. nvgBeginPath(vg);
  208. nvgMoveTo( vg, x, 0 );
  209. nvgLineTo( vg, x, box.size.y - 1 );
  210. nvgStroke( vg );
  211. x += m_divw;
  212. }
  213. y = 0.0;
  214. hlines = hdivs[ m_EnvData[ m_currentChannel ].m_Range ];
  215. divsize = box.size.y / (float)( hlines - 1 );
  216. // draw horizontal lines
  217. for( h = 0; h < hlines; h++ )
  218. {
  219. if( h == hlines / 2 && ( m_EnvData[ m_currentChannel ].m_Range == EnvelopeData::RANGE_n5to5 || m_EnvData[ m_currentChannel ].m_Range == EnvelopeData::RANGE_n10to10 || m_EnvData[ m_currentChannel ].m_Range == EnvelopeData::RANGE_Audio ) )
  220. nvgStrokeColor( vg, nvgRGBA( 255, 255, 255, 255 ) );
  221. else
  222. nvgStrokeColor( vg, nvgRGBA( 80, 80, 80, 255 ) );
  223. nvgBeginPath(vg);
  224. nvgMoveTo( vg, 0, y );
  225. nvgLineTo( vg, box.size.x - 1, y );
  226. nvgStroke( vg );
  227. y += divsize;
  228. }
  229. if( m_EnvData[ m_currentChannel ].m_bGateMode )
  230. {
  231. // draw rects
  232. for( h = 0; h < ENVELOPE_DIVISIONS; h++ )
  233. {
  234. nvgBeginPath(vg);
  235. nvgRect( vg, h * m_divw, ( 1.0f - m_EnvData[ m_currentChannel ].m_HandleVal[ h ] ) * box.size.y, m_divw, box.size.y * m_EnvData[ m_currentChannel ].m_HandleVal[ h ] );
  236. nvgFillColor(vg, nvgRGBA( 157, 100, 100, 128 ) );
  237. nvgFill(vg);
  238. }
  239. }
  240. else
  241. {
  242. nvgStrokeColor( vg, nvgRGBA( 255, 255, 255, 255 ) );
  243. nvgBeginPath(vg);
  244. x = 0;
  245. nvgMoveTo( vg, x, ( 1.0f - m_EnvData[ m_currentChannel ].m_HandleVal[ 0 ] ) * box.size.y );
  246. // draw lines
  247. for( h = 1; h < ENVELOPE_HANDLES; h++ )
  248. {
  249. x += m_divw;
  250. nvgLineTo( vg, x, ( 1.0f - m_EnvData[ m_currentChannel ].m_HandleVal[ h ] ) * box.size.y );
  251. }
  252. nvgStroke( vg );
  253. x = 0;
  254. // draw handles
  255. for( h = 0; h < ENVELOPE_DIVISIONS + 1; h++ )
  256. {
  257. nvgBeginPath(vg);
  258. y = ( 1.0f - m_EnvData[ m_currentChannel ].m_HandleVal[ h ] ) * box.size.y;
  259. nvgRect( vg, x - m_handleSizeD2, y - m_handleSizeD2, m_handleSize, m_handleSize );
  260. nvgFillColor(vg, nvgRGBA( m_HandleCol[ h ].Col[ 2 ], m_HandleCol[ h ].Col[ 1 ], m_HandleCol[ h ].Col[ 0 ],255 ) );
  261. nvgFill(vg);
  262. x += m_divw;
  263. }
  264. }
  265. // draw indicator line
  266. if( m_EnvData[ m_currentChannel ].m_Range != EnvelopeData::RANGE_Audio )
  267. {
  268. nvgStrokeColor( vg, nvgRGBA( 255, 255, 255, 80 ) );
  269. nvgBeginPath(vg);
  270. nvgMoveTo( vg, m_EnvData[ m_currentChannel ].m_fIndicator * box.size.x, 0 );
  271. nvgLineTo( vg, m_EnvData[ m_currentChannel ].m_fIndicator * box.size.x, box.size.y );
  272. nvgStroke( vg );
  273. }
  274. }
  275. //-----------------------------------------------------
  276. // Procedure: onMouseDown
  277. //-----------------------------------------------------
  278. void Widget_EnvelopeEdit::onMouseDown( EventMouseDown &e )
  279. {
  280. int index;
  281. m_Drag = -1;
  282. e.consumed = false;
  283. OpaqueWidget::onMouseDown( e );
  284. if( !m_bInitialized )
  285. return;
  286. if( e.button == 0 )
  287. {
  288. if( !m_bDraw )
  289. windowCursorLock();
  290. if( m_EnvData[ m_currentChannel ].m_bGateMode )
  291. m_Drag = clamp( ( e.pos.x / box.size.x ) * (float)ENVELOPE_DIVISIONS, 0.0f, (float)(ENVELOPE_DIVISIONS - 1) );
  292. else
  293. m_Drag = clamp( ( ( e.pos.x + (m_divw / 2.0f) ) / box.size.x ) * (float)ENVELOPE_DIVISIONS, 0.0f, (float)ENVELOPE_DIVISIONS );
  294. m_bDrag = true;
  295. }
  296. else if( e.button == 1 )
  297. {
  298. if( m_EnvData[ m_currentChannel ].m_bGateMode )
  299. index = clamp( ( e.pos.x / box.size.x ) * (float)ENVELOPE_DIVISIONS, 0.0f, (float)(ENVELOPE_DIVISIONS - 1) );
  300. else
  301. index = clamp( ( ( e.pos.x + (m_divw / 2.0f) ) / box.size.x ) * (float)ENVELOPE_DIVISIONS, 0.0f, (float)ENVELOPE_DIVISIONS );
  302. m_EnvData[ m_currentChannel ].m_HandleVal[ index ] = 0.0f;
  303. }
  304. }
  305. //-----------------------------------------------------
  306. // Procedure: onDragStart
  307. //-----------------------------------------------------
  308. void Widget_EnvelopeEdit::onDragStart(EventDragStart &e)
  309. {
  310. e.consumed = true;
  311. //windowCursorLock();
  312. }
  313. //-----------------------------------------------------
  314. // Procedure: onDragEnd
  315. //-----------------------------------------------------
  316. void Widget_EnvelopeEdit::onDragEnd(EventDragEnd &e)
  317. {
  318. e.consumed = true;
  319. windowCursorUnlock();
  320. m_Drag = -1;
  321. }
  322. //-----------------------------------------------------
  323. // Procedure: onMouseMove
  324. //-----------------------------------------------------
  325. void Widget_EnvelopeEdit::onMouseMove( EventMouseMove &e )
  326. {
  327. OpaqueWidget::onMouseMove( e );
  328. if( m_bDrag && m_bDraw )
  329. {
  330. m_Drawy = e.pos.y;
  331. if( m_EnvData[ m_currentChannel ].m_bGateMode )
  332. m_Drag = clamp( ( e.pos.x / box.size.x ) * (float)ENVELOPE_DIVISIONS, 0.0f, (float)(ENVELOPE_DIVISIONS - 1) );
  333. else
  334. m_Drag = clamp( ( ( e.pos.x + (m_divw / 2.0f) ) / box.size.x ) * (float)ENVELOPE_DIVISIONS, 0.0f, (float)ENVELOPE_DIVISIONS );
  335. }
  336. }
  337. //-----------------------------------------------------
  338. // Procedure: onDragMove
  339. //-----------------------------------------------------
  340. void Widget_EnvelopeEdit::onDragMove(EventDragMove &e)
  341. {
  342. int h, i;
  343. float fband;
  344. float delta = 0.001f;
  345. e.consumed = true;
  346. if( !m_bInitialized || !m_bDrag )
  347. return;
  348. if( !m_bDraw )
  349. {
  350. // Drag slower if Mod is held
  351. if (windowIsModPressed())
  352. delta = 0.00001f;
  353. m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ] -= delta * e.mouseRel.y;
  354. m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ] = clamp( m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ], 0.0f, 1.0f );
  355. if( m_pCallback )
  356. m_pCallback( m_pClass, m_EnvData[ m_currentChannel ].getActualVal( m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ] ) );
  357. if( m_fband > 0.0001 )
  358. {
  359. fband = m_fband;
  360. for( h = -1; h > -4; h -- )
  361. {
  362. i = m_Drag + h;
  363. if( i < 0 )
  364. break;
  365. m_EnvData[ m_currentChannel ].m_HandleVal[ i ] -= (delta * e.mouseRel.y) * fband;
  366. m_EnvData[ m_currentChannel ].m_HandleVal[ i ] = clamp( m_EnvData[ m_currentChannel ].m_HandleVal[ i ], 0.0f, 1.0f );
  367. fband *= 0.6f;
  368. }
  369. fband = m_fband;
  370. for( h = 1; h < 4; h ++ )
  371. {
  372. i = m_Drag + h;
  373. if( i > ENVELOPE_DIVISIONS )
  374. break;
  375. m_EnvData[ m_currentChannel ].m_HandleVal[ i ] -= (delta * e.mouseRel.y) * fband;
  376. m_EnvData[ m_currentChannel ].m_HandleVal[ i ] = clamp( m_EnvData[ m_currentChannel ].m_HandleVal[ i ], 0.0f, 1.0f );
  377. fband *= 0.6f;
  378. }
  379. recalcLine( -1, m_Drag );
  380. }
  381. else
  382. {
  383. recalcLine( m_currentChannel, m_Drag );
  384. }
  385. }
  386. else
  387. {
  388. m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ] = 1.0 - ( m_Drawy / box.size.y );
  389. m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ] = clamp( m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ], 0.0f, 1.0f );
  390. if( m_pCallback )
  391. m_pCallback( m_pClass, m_EnvData[ m_currentChannel ].getActualVal( m_EnvData[ m_currentChannel ].m_HandleVal[ m_Drag ] ) );
  392. recalcLine( m_currentChannel, m_Drag );
  393. }
  394. }
  395. //-----------------------------------------------------
  396. // Procedure: setBeatLen
  397. //-----------------------------------------------------
  398. void Widget_EnvelopeEdit::setBeatLen( int len )
  399. {
  400. m_BeatLen = len;
  401. m_bClkd = true;
  402. if( m_BeatLen <= 0 )
  403. return;
  404. for( int i = 0; i < MAX_ENVELOPE_CHANNELS; i++ )
  405. {
  406. switch( m_TimeDiv[ i ] )
  407. {
  408. case TIME_64th:
  409. m_EnvData[ i ].m_Clock.syncInc = ( ( engineGetSampleRate() / (float)m_BeatLen ) * 16.0 ) / 16.0;
  410. break;
  411. case TIME_32nd:
  412. m_EnvData[ i ].m_Clock.syncInc = ( ( engineGetSampleRate() / (float)m_BeatLen ) * 8.0 ) / 16.0;
  413. break;
  414. case TIME_16th:
  415. m_EnvData[ i ].m_Clock.syncInc = ( ( engineGetSampleRate() / (float)m_BeatLen ) * 4.0 ) / 16.0;
  416. break;
  417. case TIME_8th:
  418. m_EnvData[ i ].m_Clock.syncInc = ( ( engineGetSampleRate() / (float)m_BeatLen ) * 2.0 ) / 16.0;
  419. break;
  420. case TIME_4tr:
  421. m_EnvData[ i ].m_Clock.syncInc = ( ( engineGetSampleRate() / (float)m_BeatLen ) * 1.0 ) / 16.0;
  422. break;
  423. case TIME_Bar:
  424. m_EnvData[ i ].m_Clock.syncInc = ( ( engineGetSampleRate() / (float)m_BeatLen ) * 0.25 ) / 16.0;
  425. break;
  426. }
  427. }
  428. }
  429. //-----------------------------------------------------
  430. // Procedure: procStep
  431. //-----------------------------------------------------
  432. float Widget_EnvelopeEdit::procStep( int ch, bool bTrig, bool bHold )
  433. {
  434. if( ( m_bClkReset || bTrig ) && !bHold )
  435. {
  436. if( m_EnvData[ ch ].m_Mode == EnvelopeData::MODE_REVERSE )
  437. m_EnvData[ ch ].m_Clock.fpos = engineGetSampleRate();
  438. else
  439. m_EnvData[ ch ].m_Clock.fpos = 0;
  440. }
  441. return m_EnvData[ ch ].procStep( bTrig, bHold );
  442. }