It is currently April 18th, 2024, 4:59 pm

Clickable Circular Dial Using Mouse Variables

Tips and Tricks from the Rainmeter Community
User avatar
killall-q
Posts: 305
Joined: August 14th, 2009, 8:04 am

Clickable Circular Dial Using Mouse Variables

Post by killall-q »

If you've ever used a volume dial skin, you've probably had a natural impulse to click it to set the volume at some point. Today, we're going to satisfy that impulse.

We start with mouse variables and arctangent, which allows us to derive an angle from any 2 points. The first point will be the center of the meter, and the 2nd will be the click coordinates. We'll write a formula that causes the bottom left to approach 0, and the bottom right to approach 1.

Using percentage mouse variables will free us from worrying about the dimensions of the meter in question. The percentage is an integer ranging from 0-100. Arctangent takes the ratio of Y-axis change to X-axis change, so we get that relative to the center by subtracting 50% from both mouse variables. Atan() gives results ranging from -pi/2 to pi/2 on the right half of the circle, and inverted (rotational symmetry) on the left side. Adding pi/2 to the result will shift the range to 0 to pi. Then we add pi if click is on the right side to get an angle that ranges from 0 to 2pi. Divide the result by 2pi to get a value that ranges from 0 to 1.

After reordering some operations for efficiency, we get:

Code: Select all

!SetVariable Num (Atan(($MouseY:%$-50)/($MouseX:%$-50))/6.2832+0.25+(Sgn($MouseX:%$-50)+1)*0.25)
But this solution has problems. First off, the clickarea to set 0 is right next to the clickarea to set 1. Secondly, if you click in the vertical center of the meter, you get a divide by zero error, which destroys the universe. We'll worry about the second problem later.

Ideally, there should slightly larger click areas solely for setting 0 or 1. We'll accomodate that by changing the formula to range from slightly less than 0 to slightly greater than 1. Specifically, I'm going to carve out the bottom 1/8th of the circle for those areas.

Code: Select all

!SetVariable Num (Atan(($MouseY:%$-50)/($MouseX:%$-50))/5.49779+0.21875+(Sgn($MouseX:%$-50)+1)*0.28125)
Well, that was easy. I divided the Atan() by a further 7/8, which I factored into the 2pi. I then shifted the results below 0 and above 1 by 1/32 (don't ask me why), which I factored into the 0.25's.

Conveniently, Lua's math.atan2 takes care of divide-by-zero. It also gives angles for the full circle by checking the signs of parameters. The result ranges from -pi to pi.

Code: Select all

math.atan2(mouseX-50, 50-mouseY) / 5.49779 + 0.5
I deliberately used the parameters in the wrong order and sign to avert rotating/flipping transformations later.

Then to use it for volume, I multiply the constants by 100. I also precalculate 1/5.49779 because multiplication is more efficient than division for computers.

TL;DR

100 * (1 / (2pi * 7/8)) ≈ 18.18914

Replace 7/8 with any fraction to make semi-circle dials, etc.

Code: Select all

[Dial]
Meter=Roundline
LeftMouseUpAction=!CommandMeasure mScript SetVolume($MouseX:%$,$MouseY:%$)

function SetVolume(mouseX, mouseY)
   SKIN:Bang('!CommandMeasure mVolume "SetVolume '..(math.atan2(mouseX-50, 50-mouseY) * 18.18914 + 50)..'"')
end
Image
VolumeDial.rmskin
Changelog:
- Added center mute button from smurfier's RoundKnob.
- Detect mute state.
You do not have the required permissions to view the files attached to this post.
Last edited by killall-q on August 27th, 2014, 4:43 am, edited 3 times in total.
User avatar
smurfier
Moderator
Posts: 1931
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: Clickable Circular Dial Using Mouse Variables

Post by smurfier »

GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
killall-q
Posts: 305
Joined: August 14th, 2009, 8:04 am

Re: Clickable Circular Dial Using Mouse Variables

Post by killall-q »

Alright, fine, you beat me. I had no idea. But I accomodated the 0%/100% clickareas usability issue. I like the center mute button, I think I'll steal that.
User avatar
smurfier
Moderator
Posts: 1931
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: Clickable Circular Dial Using Mouse Variables

Post by smurfier »

I made mine more as a proof of concept than an actual skin. My skills lie more in the coding than in the making things pretty so people will download them.
GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
iNjUST
Posts: 117
Joined: June 20th, 2012, 12:44 am

Re: Clickable Circular Dial Using Mouse Variables

Post by iNjUST »

moshi also made a volume skin along these lines a while ago, although smurfier still seems to be first, and moshi's doesn't utilize Mouse Variables or trigonometry, but merely brute force lots of hidden hotspot meters. His, however, is draggable (you can manually grab and twist the knob).

However, his inspired me to make my own draggable round knob, but more elegantly using Mouse Variables (and I didn't have any knowledge of smurfier's skin). I never released it or finished it, but you can check the reddit thread from a year ago where I was showing some progress on a suite of skins including it.

And for funzies, here's the current state of that skin of mine, if anyone feels like toying with or dissecting it:
Dynaknob Alpha_0.1.rmskin
You do not have the required permissions to view the files attached to this post.
User avatar
killall-q
Posts: 305
Joined: August 14th, 2009, 8:04 am

Re: Clickable Circular Dial Using Mouse Variables

Post by killall-q »

That's really ingenious, and looks crazy good for something not using any images, but I don't know if the functionality is worth sacrificing the ability to drag the skin.

If you release the mouse button outside the skin, it gets stuck. You need this:

Code: Select all

[Rainmeter]
MouseLeaveAction=!HideMeterGroup Hover
User avatar
iNjUST
Posts: 117
Joined: June 20th, 2012, 12:44 am

Re: Clickable Circular Dial Using Mouse Variables

Post by iNjUST »

killall-q wrote:That's really ingenious, and looks crazy good for something not using any images, but I don't know if the functionality is worth sacrificing the ability to drag the skin.

If you release the mouse button outside the skin, it gets stuck. You need this:

Code: Select all

[Rainmeter]
MouseLeaveAction=!HideMeterGroup Hover
Thanks for the tip! And yeah, my personal rainmeter-ing goal is always to draw everything as variable- and style-driven, scalable, and relying as little as possible on images, while still looking nice.

Ctrl+Click for dragging the skin around has never been a significant detractor for me, but I understand how that could get in some people's way. Maybe I could modify it somehow so if you click in the center of the knob it allows dragging the skin, but clicking around the edges adjusts the volume. And I am sometimes picky about volume values (even increments), so the "twistable" functionality of the knob auto-snaps to 5% increments, whereas just clicking sets the volume precisely within 1%.

I like your lua example, and being able to account for the signs of the inputs and division by zero automatically. That's something that was a pain in my skin.
User avatar
killall-q
Posts: 305
Joined: August 14th, 2009, 8:04 am

Re: Clickable Circular Dial Using Mouse Variables

Post by killall-q »

The only way I can see you making the center draggable is by using 4 or 8 meters for picking up !LeftMouseDownAction so they don't block the center. They'd each send their mouse variables and an identifier to Lua, then it would only take a little math to figure out where the click was in relation to the whole skin.

You're just going to have to give in to Lua... I used to build Rube Goldberg machines in pure Rainmeter too, until I saw how much time I wasted relearning how my own stuff worked every time I went back to something I'd been away from a few days.