How to smoothly rotate knob with mouse ?
-
- KVRian
- Topic Starter
- 833 posts since 21 Feb, 2006 from FI
Hello!
I'm thinking to use this type technique for to rotate a knob with mouse :
Lets say, there's image list for 100 knob positions (0-99) covering rotation "range" -140.0 to 140.0 degrees. It's for to adjust the gain in "range" -12.0 to 12.0 dB. Linear scale so image 49 = 0dB.
1. when focus is in knob image; calculate the current "base" direction (image center - knob's position mark) (t0 = atan2(markY - centerY, markX - centerX) * 360 / 2pi)
2. when left mouse is pressed down and ready for dragging; set the "working" direction t1 = atan2(mouseY - centerY, mouseX - centerX) * 360 / 2pi
3. when mouse is moved (dragged); calculate the "current" direction t2 = atan2(currentMouseY - centerY, currentMouseX - centerX) * 360 / 2pi
4. calculate the "angle" between the "current" and "working" direction (alfa = t2 - t1)
5. sum the "angle" with "base" direction (check that "ranges" are not past) (t = t0 + alfa)
6. calculate the new image index using certain formula
- loop 3-6 as long as mouse is been dragged
Is this too complicated method? Any bottlenecks? Any suggestions for better techniques?
I'm thinking to use this type technique for to rotate a knob with mouse :
Lets say, there's image list for 100 knob positions (0-99) covering rotation "range" -140.0 to 140.0 degrees. It's for to adjust the gain in "range" -12.0 to 12.0 dB. Linear scale so image 49 = 0dB.
1. when focus is in knob image; calculate the current "base" direction (image center - knob's position mark) (t0 = atan2(markY - centerY, markX - centerX) * 360 / 2pi)
2. when left mouse is pressed down and ready for dragging; set the "working" direction t1 = atan2(mouseY - centerY, mouseX - centerX) * 360 / 2pi
3. when mouse is moved (dragged); calculate the "current" direction t2 = atan2(currentMouseY - centerY, currentMouseX - centerX) * 360 / 2pi
4. calculate the "angle" between the "current" and "working" direction (alfa = t2 - t1)
5. sum the "angle" with "base" direction (check that "ranges" are not past) (t = t0 + alfa)
6. calculate the new image index using certain formula
- loop 3-6 as long as mouse is been dragged
Is this too complicated method? Any bottlenecks? Any suggestions for better techniques?
-
- KVRian
- Topic Starter
- 833 posts since 21 Feb, 2006 from FI
Simplier technique, where just the direction (angle) between mouseXY and centerXY is used works otherwise well (knob marker follows the mouse cursor)
but one issue ... when mouse is down and moved a bit, knob rotates to point the current mouseXY direction (using the technique in 1st post should fix this).
Code: Select all
private: System::Void HandleKnobMovement(PictureBox^ picBox, NumericUpDown^ lbl, MouseEventArgs^ e, int type, int band){
//global_sw->WriteLine("HandleKnobMovement()");
// type = hz, bwq, gain
bool valid = true;
if (picBox->Enabled){ lbl->Focus(); } // numericupdown control allows use of mousewheel --> rotate the knob through this control
if (GetKeyState(VK_LBUTTON) < 0){ // left button must be down
int max = 99; // bw
int idx = 0;
switch (type){
case 0: // hz
max = 199;
break;
case 1: // bw
break;
case 2: // gain
max = 179;
break;
case 3: // masterGain
max = 119;
}
// new coordinate system
double dx = (e->X - (picBox->Width / 2));
double dy = ((picBox->Height / 2) - e->Y);
double value = 0.0; // value for numericupdown control
double expVal = 0.0;
double alfa = atan2(dx, dy) * 360.0 / (2 * 3.14159265); // range -180.0, 180.0
if (alfa < -140.0){ alfa = -140.0; }
if (alfa > 140.0){ alfa = 140.0; }
switch (type){
case 0: // Hz (logarithmic knob)
idx = 0.7107142857 * alfa + 99.5000001;
if (idx < 0){ idx = 0; }
if (idx > max){ idx = max; }
picBox->Image = HzKnob->Images[idx]; // set new image
expVal = exp(0.0271460802 * alfa);
value = 447.2135955 * expVal;
if (value < 10){ value = 10; }
if (value > 20000){ value = 20000; }
break;
case 1: // BWoct/Q (logaritmic knob)
// 1 = null
// 2 = bw
// 3 = Q
idx = 0.3535714286 * alfa + 49.5;
if (idx < 0){ idx = 0; }
if (idx > max){ idx = max; }
if (bandData[currentSpeakerMode][currentChannel][band].BwQNull == 2){ // bw/oct
picBox->Image = BWQKnob->Images[idx];
expVal = exp(0.0221950289 * alfa);
value = 0.4472135955 * expVal;
if (value < 0.02){ value = 0.02; }
if (value > 10.0){ value = 10.0; }
}
else if (bandData[currentSpeakerMode][currentChannel][band].BwQNull == 3){ // Q
picBox->Image = BWQKnob->Images[idx];
expVal = exp(-0.0277972286 * alfa);
value = 1.4696938457 * expVal;
if (value < 0.03){ value = 0.03; }
if (value > 72.0){ value = 72.0; }
}
else{ // -
value = 0.0;
}
break;
case 2: // Gain (linear)
idx = 0.639285714 * alfa + 89.5000001;
if (idx < 0){ idx = 0; }
if (idx > max){ idx = max; }
picBox->Image = GainKnob->Images[idx];
value = 0.1285714286 * alfa; // 0.2011173184 * idx - 18;
if (value < -18.0){ value = -18.0; }
if (value > 18.0){ value = 18.0; }
break;
case 3: //Master Gain (linear)
idx = 0.428571426 * alfa + 60.000001; //
if (idx > max){ idx = max; }
if (idx < 0){ idx = 0; }
picBox->Image = masterGainKnob->Images[idx];
value = 0.0857142857 * alfa;
if (value > 12.0){ value = 12.0; }
if (value < -12.0){ value = -12.0; }
break;
}
lbl->Value = System::Convert::ToDecimal(value); // update numericupdown control (triggers some other calls)
updateBandChanges(band, false); //
}
}
- KVRAF
- 2554 posts since 4 Sep, 2006 from 127.0.0.1
what you're describing is circular response, i hate it
but you could set up a minimum distance from the center where you can ignore the mouse and not change the knob position
distance formula is: sqrt(dx*dx+dy*dy) where dx=centerX-mouseX; dy=centerY-mouseY;
and i would advise you to have an odd number of frames for your knob, so that there is one frame exactly in the middle
but you could set up a minimum distance from the center where you can ignore the mouse and not change the knob position
distance formula is: sqrt(dx*dx+dy*dy) where dx=centerX-mouseX; dy=centerY-mouseY;
and i would advise you to have an odd number of frames for your knob, so that there is one frame exactly in the middle
It doesn't matter how it sounds..
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
..as long as it has BASS and it's LOUD!
irc.libera.chat >>> #kvr
-
- KVRian
- Topic Starter
- 833 posts since 21 Feb, 2006 from FI
Thanks for the reply and advising (I almost started to think this is one of those hush hush subjects ... )
I quess the other way is to use the length of mouse movement in calculation of rotation angle (frame index) and equivalent value ... or are there other techniques ...?
Selection of the "circular response" method was based on thought that it would be easier to
- "fine tune" the knob already with mouse because of finer tuning capability is there already without extra coding needed (drag mouse further from the coordinate center = smaller angle division)
- calculate the image list index and value directly from angle (I'm using simple trendline formulas got from OOCalc graph)
I quess the other way is to use the length of mouse movement in calculation of rotation angle (frame index) and equivalent value ... or are there other techniques ...?
Selection of the "circular response" method was based on thought that it would be easier to
- "fine tune" the knob already with mouse because of finer tuning capability is there already without extra coding needed (drag mouse further from the coordinate center = smaller angle division)
- calculate the image list index and value directly from angle (I'm using simple trendline formulas got from OOCalc graph)