It is currently April 23rd, 2024, 12:17 pm

Help to rotate skin

Get help with creating, editing & fixing problems with skins
User avatar
ftrement
Posts: 14
Joined: April 20th, 2020, 11:54 am
Location: Italy

Help to rotate skin

Post by ftrement »

Good evening to all...I'm pratically new in rainmeter, I'm learning.
I'm not sure how to rotate my skin, I think I need to modify the code, but I'm not sure on the lines to be written. The skin to rotate is Frost music visualizer. I want to align the visualizer with the bottom part of the Joker's card...inside
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 7149
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Help to rotate skin

Post by Yincognito »

Basically, what should be done is to change the String option from the [Matrix] meter in C:\Users\[username]\Documents\Rainmeter\Skins\Frost\@Resources\Frost.inc. I'll see what I can do - so far I rotated it to 45 degrees, but have to play a bit with it so it doesn't go outside the actual meter frame. For reference, the transformation matrix formulas for rotating are here (the Transformations section).
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7149
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Help to rotate skin

Post by Yincognito »

Note: You may want to comment the lines I'm talking below (by adding a ; in front of them) instead of replacing them, so that you can switch back to how it was by toggling the commenting (adding/removing the ; from the start of a line) back and forth between the "old" and the "new" lines.

So, adding into the C:\Users\[username]\Documents\Rainmeter\Skins\Frost\@Resources\Frost.inc file the following:
- a variable Angle=225 in the [Variables] section of the .inc file
- replacing the String option in the [Matrix] meter from the same file with:

Code: Select all

String="(Cos(Rad(#Angle#))*#Scale#);(-Sin(Rad(#Angle#)));(Sin(Rad(#Angle#)));(Cos(Rad(#Angle#))*#Scale#);((#Width#*#Scale#*0.5)-(#Width#*#Scale#*0.5)*Cos(Rad(#Angle#))-(#Height#*#Scale#*0.5)*Sin(Rad(#Angle#)));((#Height#*#Scale#*0.5)+(#Width#*#Scale#*0.5)*Sin(Rad(#Angle#))-(#Height#*#Scale#*0.5)*Cos(Rad(#Angle#)))"
- replacing the W and H lines in the [BoundingBox] meter from the same file with:

Code: Select all

W=((#Horizontal# = 0 ? #Width# : #Height#) * #Scale# * 2)
H=((#Horizontal# = 0 ? #Height# : #Width#) * #Scale# * 2)
SolidColor=0,0,0,128
"almost" does it (it rotates the bands 45 degrees counter-clockwise, and enlarges the "bounding box" that holds them and makes it slightly visible, so that one can see what happens). It's not yet complete, it's merely an (unfinished) attempt - probably some help from balala (our TransformationMatrix expert here) would be welcomed. It takes patience to tweak the transformation matrix stuff, and mine is fading rapidly on this one... :D

P.S. The problem with this skin is that the Lua scripts are modifying / setting the widths / heights of the Rotator meters based on some formulas that are probably best known by the actual skin developer. This makes the task of enlarging those meters to fit the rotated results above quite difficult. Also, the skin developer's "shotcuts" / "abbreviation aliases" for nearly every bang doesn't make the task easier either ...
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7149
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Help to rotate skin

Post by Yincognito »

ftrement wrote: April 25th, 2020, 5:31 pm Good evening to all...I'm pratically new in rainmeter, I'm learning.
I'm not sure how to rotate my skin, I think I need to modify the code, but I'm not sure on the lines to be written. The skin to rotate is Frost music visualizer. I want to align the visualizer with the bottom part of the Joker's card...inside
Ok, after some relax time, I finally got the right approach to this. As expected, the Lua code had to be also modified for everything to work properly. What you need to do is:

1. Replace the code in C:\Users\[yourusername]\Documents\Rainmeter\Skins\Frost\@Resources\SetMeterOptions.lua with:

Code: Select all

function Update()
  local width, height = SKIN:ParseFormula(SKIN:GetVariable("Width")), SKIN:ParseFormula(SKIN:GetVariable("Height"))
  local horizontal = SKIN:ParseFormula(SKIN:GetVariable("Horizontal"))
  local meterName = {}
  
  for i = 1 + 1, width + 1 do
    meterName[i] = "MeterRotator" .. i-1
	if SKIN:GetMeter(meterName[i]) == nil then return 0 end
    SKIN:Bang("!SetOption", meterName[i], "Group", "Rotators")
    SKIN:Bang("!UpdateMeter", meterName[i])
  end
  
  -- for i = 1 + 1, width + 1 do
	-- if horizontal == 0 then SKIN:Bang("!SetOption", meterName[i], "X", i-2)
	-- else SKIN:Bang("!SetOption", meterName[i], "Y", i-2) end
  -- end
  
  for i = 1 + 1, width + 1 do
	SKIN:Bang("!SetOption", meterName[i], "X", (((width ^ 2 + height ^ 2) ^ 0.5 - width) / 2) + (width + 1 - 2) - (i - 2))
	SKIN:Bang("!SetOption", meterName[i], "Y", (((width ^ 2 + height ^ 2) ^ 0.5 - height) / 2))
  end

  if horizontal == 0 then
    SKIN:Bang("!SetOptionGroup", "Rotators", "GradientAngle", 90)
    SKIN:Bang("!SetOptionGroup", "Rotators", "W", 1)
  else SKIN:Bang("!SetOptionGroup", "Rotators", "H", 1) end
  
  SKIN:Bang("!SetOptionGroup", "Rotators", "SolidColor", "#Color#,255")
  SKIN:Bang("!SetOptionGroup", "Rotators", "SolidColor2", "#Color#,0")
  
  SKIN:Bang("!SetOptionGroup", "Rotators", "TransformationMatrix", SKIN:GetMeasure("Matrix"):GetStringValue())
  SKIN:Bang("!UpdateMeterGroup", "Rotators")
  SKIN:Bang("!SetOptionGroup", "Rotators", "TransformationMatrix", "")
  
  SKIN:Bang("!UpdateMeterGroup","Rotators")
end
2. Replace the code in C:\Users\[yourusername]\Documents\Rainmeter\Skins\Frost\@Resources\Frost.inc with:

Code: Select all

[Rainmeter]
Update=16
DefaultUpdateDivider=-1
Group=#SkinGroup#
OnCloseAction=[!RefreshGroup #SkinGroup#]
LeftMouseUpAction=#OpenSettingsWindow#

ContextTitle="Open settings window"
ContextAction=#OpenSettingsWindow#
ContextTitle2="Edit variables"
ContextAction2=["#@#Variables.inc"]

[Variables]
Angle=225

; Since each skin file has some specific settings, they should be written to the global Variables file for access
EnvFlip=[!WriteKeyValue Variables Flip #Flip# "#@#Variables.inc"]
EnvHorizontal=[!WriteKeyValue Variables Horizontal #Horizontal# "#@#Variables.inc"]
EnvInvert=[!WriteKeyValue Variables Invert #Invert# "#@#Variables.inc"]
EnvChannel=[!WriteKeyValue Variables Channel #Channel# "#@#Variables.inc"]
EnvPort=[!WriteKeyValue Variables Port #Port# "#@#Variables.inc"]
EnvID=[!WriteKeyValue Variables ID "#ID#" "#@#Variables.inc"]
EnvConfig=[!WriteKeyValue Variables Config "#CURRENTCONFIG#" "#@#Variables.inc"]
EnvConfigPath=[!WriteKeyValue Variables ConfigPath "#CURRENTPATH##CURRENTFILE#" "#@#Variables.inc"]
EnvSettingsWindow=#EnvFlip##EnvHorizontal##EnvInvert#EnvChannel##EnvPort##EnvID##EnvConfig##EnvConfigPath#
OpenSettingsWindow=#EnvSettingsWindow#[!ActivateConfig "#ROOTCONFIG#\SettingsWindow"][!Refresh "#ROOTCONFIG#\SettingsWindow"]

[DisableProcessCheck]
Measure=String
String=#MusicPlayer#
IfMatch="None"
IfMatchAction=[!SetOption DisableProcessCheck String 1][!UpdateMeasure DisableProcessCheck]
IfNotMatchAction=[!SetOption MeasureProcess UpdateDivider 62.5]

[MeasureProcess]
Measure=Plugin
Plugin=Process
ProcessName=#MusicPlayer#.exe

[IdleAudioTimeout]
Measure=Calc
Formula=(IdleAudioTimeout + 1)
IfCondition=(IdleAudioTimeout = (Floor(62.5 * #IdleAudioTimeout#)))
IfTrueAction=[!DisableMeasure MeasureAudio][!DisableMeasureGroup Audio][!DisableMeasure ScriptFrost][!DisableMeasure DynamicSensitivity][!DisableMeasure IdleAudioTimeout]
UpdateDivider=1

[Standby]
Measure=Plugin
Plugin=AudioLevel
Port=#Port#
ID=#ID#
RMSAttack=0
RMSDecay=0
RMSGain=1
PeakAttack=0
PeakDecay=0
PeakGain=1
UpdateDivider=1

; Toggle measures/meters based on idle audio and music player running status
IfCondition=((Standby > 0.00001) && ((DisableProcessCheck = 1) || (MeasureProcess = 1)))
IfTrueAction=[!DisableMeasure IdleAudioTimeout][!EnableMeasure MeasureAudio][!EnableMeasureGroup Audio][!EnableMeasure ScriptFrost][!EnableMeasure DynamicSensitivity]
IfFalseAction=[!EnableMeasure IdleAudioTimeout]

[MeasureAudio]
Measure=Plugin
Plugin=AudioLevel
Port=#Port#
ID=#ID#
RMSAttack=0
RMSDecay=0
RMSGain=1
PeakAttack=0
PeakDecay=0
PeakGain=1
FFTSize=#FFTSize#
FFTOverlap=(Min(#FFTOverlap#, (#FFTSize#-512)))
FFTAttack=#FFTAttack#
FFTDecay=#FFTDecay#
Bands=#Bands#
FreqMin=#FreqMin#
FreqMax=#FreqMax#
Sensitivity=#Sensitivity#
UpdateDivider=1

[DynamicSensitivity]
Measure=Calc
Formula=(Max(#Sensitivity#, Min(Abs(20 * Log(MeasureAudio)) + Abs(20 * Log(0.5)), 0.5 * Abs(20 * Log(1/65535)))))
IfCondition=(#LoudnessEqualization# = 1)
IfTrueAction=[!SetOption MeasureAudio Sensitivity [DynamicSensitivity]]
IfConditionMode=1
UpdateDivider=1
; Average over the past 0.5 seconds to prevent stuttering
AverageSize=31

@Include=#@#BandMeasures.inc
@Include2=#@#BandMeters.inc

[SetMeasureOptions]
Measure=Calc
OnUpdateAction=[!SetOptionGroup Audio Channel #Channel#][!SetOptionGroup Audio AverageSize #AverageSize#][!SetOptionGroup Audio UpdateDivider 1][!UpdateMeasureGroup Audio]

[SetMeterOptions]
Measure=Script
ScriptFile=#@#SetMeterOptions.lua

[ScriptFrost]
Measure=Script
ScriptFile=#@#Frost.lua
MeasureBaseName=MeasureAudio
MeterBaseName=MeterRotator
hLowerLimit=#FirstBandIndex#
hUpperLimit=(#Bands#-1)
InterpolateSpan=(Ceil(#Width# / (#Bands# - #FirstBandIndex# - 1)))
SpectrumSize=#Width#
MeterDimSize=#Height#
SmoothEnds=#SmoothEnds#
SetH=(#Horizontal# = 0 ? 1 : 0)
UpdateDivider=1
OnUpdateAction=[!Redraw]

[Matrix]
Measure=String
;String="(#Horizontal# = 0 ? #Scale# : (#Flip# = 0 ? #Scale# : -#Scale#));0;0;(#Horizontal# = 0 ? (#Flip# = 0 ? -#Scale# : #Scale#) : #Scale#);(#Horizontal# = 0 ? 0 : (#Flip# = 0 ? 0 : (#Height# * #Scale#)));(#Horizontal# = 0 ? (#Flip# = 0 ? (#Height# * #Scale#) : 0) : 0)"
String="(Cos(Rad(#Angle#))*#Scale#);(-Sin(Rad(#Angle#))*#Scale#);(Sin(Rad(#Angle#))*#Scale#);(Cos(Rad(#Angle#))*#Scale#);(((((Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))-(#Width#*#Scale#))/2)+#Width#*#Scale#*0.5)-((((Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))-(#Width#*#Scale#))/2)+#Width#*#Scale#*0.5)*Cos(Rad(#Angle#))-((((Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))-(#Height#*#Scale#))/2)+#Height#*#Scale#*0.5)*Sin(Rad(#Angle#)));(((((Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))-(#Height#*#Scale#))/2)+#Height#*#Scale#*0.5)+((((Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))-(#Width#*#Scale#))/2)+#Width#*#Scale#*0.5)*Sin(Rad(#Angle#))-((((Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))-(#Height#*#Scale#))/2)+#Height#*#Scale#*0.5)*Cos(Rad(#Angle#)))"

; Reveal the transformation by expanding the skin window through an invisible meter
[BoundingBox]
Meter=Image
;W=((#Horizontal# = 0 ? #Width# : #Height#) * #Scale#)
;H=((#Horizontal# = 0 ? #Height# : #Width#) * #Scale#)
W=(Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))
H=(Sqrt((#Width#*#Scale#)**2+(#Height#*#Scale#)**2))

[MeasureZero]
Measure=Calc
Formula=0
That's it. You can change the angle by modifying the value of the Angle variable in the Frost.inc file (the angle goes counter-clockwise, with 0 being the visualizer "upside down" and 180 the visualizer in his "normal position" horizontally). Enjoy it - if you still need this, that is.

P.S. I commented the original lines that were replaced by my code instead of removing them, in case you still needed the original code for some reason. Checking the Horizontal Rotation or the Flip Upside Down checkboxes in the Settings window won't make much sense now, since the visualizer can be rotated in any position anyway, not to mention that having those boxes other than unchecked will possibly create some undesired "artefacts". Normally, one could have replaced those checkboxes with some setting to interactively change the rotation angle from the Settings skin, but that's beyond the scope of the original request/question in this thread, not to mention that it should be more or less trivial to do...
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth